Add JNI-style global references and complete GC roots - #182
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #182 +/- ##
==========================================
+ Coverage 87.03% 87.11% +0.08%
==========================================
Files 198 199 +1
Lines 17846 17947 +101
==========================================
+ Hits 15532 15635 +103
+ Misses 2314 2312 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR extends the JVM’s GC root tracking to cover Rust-owned references by introducing JNI-style global references and by treating certain API results/arguments as frame-local roots, addressing a real lifetime gap around Thread.start() and other object flows across native/Java boundaries.
Changes:
- Add RAII-managed
GlobalRef<T>backed by a global-reference table that the GC scans as a root set. - Record object arguments and returned object/exception results as frame-local references so they remain GC-visible across API boundaries.
- Update
Thread.start()to hold a global reference until the spawned callback attaches; add targeted GC regression tests.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test_utils/src/lib.rs | Adds a queued-spawn mode to deterministically delay spawn callbacks in tests. |
| jvm/tests/test_garbage_collection.rs | Adds tests covering global refs, frame-local roots for various APIs, and Thread.start() lifetime. |
| jvm/src/thread.rs | Updates Java-frame creation to seed GC-visible locals from call arguments. |
| jvm/src/lib.rs | Wires in the new global_ref module and exports GlobalRef. |
| jvm/src/jvm.rs | Implements global refs, clears bootstrap locals post-init, and roots returned object/exception values + certain API results. |
| jvm/src/global_ref.rs | Introduces GlobalReferences + RAII GlobalRef<T> with Drop cleanup. |
| jvm/src/garbage_collector.rs | Treats global references as additional GC roots. |
| java_runtime/src/classes/java/lang/thread.rs | Uses GlobalRef<Thread> to keep the thread instance alive until the spawn callback runs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Judged the two remaining remote branches on the fork: - dependabot/cargo/tracing-attributes-0.1.31: deleted. PR #4 (fa92ef9) removed the tracing-attributes direct dependency outright, so the branch patches a Cargo.toml line that no longer exists. - wie-ktf-hardening: preserved. 8 of its 12 commits are already in upstream/main via squash merges (dlunch#174 dlunch#175 dlunch#176 dlunch#177 dlunch#180 dlunch#182); git cherry missed this because origin/main trails upstream/main by 20 commits. 4 commits carry residual value. No code changes. Co-authored-by: jun0 <junyoung.choi.a@miraeasset.com> Co-authored-by: Claude <noreply@anthropic.com>
Summary
GlobalRef<T>backed by independent JVM global-reference entriesThread.start()waits for its host spawn callback to attachRoot cause
Thread.start()captured its JavaThreadinstance in a Rust callback, but the JVM garbage collector could not see Rust-owned references. If collection ran after the caller frame returned and before the spawned task attached, the thread object could be collected. The same local-reference gap existed for object values entering a frame through several JVM APIs.Validation
cargo test --workspacecargo test -p jvm --test test_garbage_collectioncargo clippy --workspace --all-targets -- -D warningscargo fmt --all -- --checkgit diff --check