Summary
NativeAOT currently has GC bridge special-casing for Java peer objects that CoreCLR/Mono do not need. We should investigate unifying the Java-side shape so the shared GC bridge can use one add/clear reference path across runtimes.
Today the shared bridge can use the classic Java peer methods:
monodroidAddReference(java.lang.Object)
monodroidClearReferences()
NativeAOT trimmable proxy objects instead implement net.dot.jni.GCUserPeerable and expose:
jiAddManagedReference(java.lang.Object)
jiClearManagedReferences()
That forces NativeAOT-specific bridge callbacks such as maybe_call_gc_user_peerable_add_managed_reference() / maybe_call_gc_user_peerable_clear_managed_references().
Proposed direction
Since NativeAOT support is still experimental, we can make breaking changes there more easily. With the trimmable type map we are already making binary-shape changes and the generated Java code is produced at app build time, so apps/libraries generally should not be relying on pre-generated .jar/.dex outputs for this path.
It may be best to move toward a single net.dot.* Java-side peer/reference shape and drop the old mono.android.* naming from this path where possible.
Benefits
- Remove NativeAOT-only GC bridge callbacks.
- Make CoreCLR and NativeAOT bridge processing more fully shared.
- Reduce runtime-specific Java peer assumptions.
- Make future GC bridge changes easier to reason about and test.
Things to check
- Whether NativeAOT trimmable proxies can expose the same add/clear method names used by the shared bridge, or whether the shared bridge should move to a new
net.dot.* interface for all supported runtimes.
- Whether any build artifacts, generated Java, manifest/provider code, or tests assume the current
GCUserPeerable method names.
- Whether moving away from
mono.android.* has compatibility implications outside the experimental NativeAOT/trimmable path.
Summary
NativeAOT currently has GC bridge special-casing for Java peer objects that CoreCLR/Mono do not need. We should investigate unifying the Java-side shape so the shared GC bridge can use one add/clear reference path across runtimes.
Today the shared bridge can use the classic Java peer methods:
monodroidAddReference(java.lang.Object)monodroidClearReferences()NativeAOT trimmable proxy objects instead implement
net.dot.jni.GCUserPeerableand expose:jiAddManagedReference(java.lang.Object)jiClearManagedReferences()That forces NativeAOT-specific bridge callbacks such as
maybe_call_gc_user_peerable_add_managed_reference()/maybe_call_gc_user_peerable_clear_managed_references().Proposed direction
Since NativeAOT support is still experimental, we can make breaking changes there more easily. With the trimmable type map we are already making binary-shape changes and the generated Java code is produced at app build time, so apps/libraries generally should not be relying on pre-generated
.jar/.dexoutputs for this path.It may be best to move toward a single
net.dot.*Java-side peer/reference shape and drop the oldmono.android.*naming from this path where possible.Benefits
Things to check
net.dot.*interface for all supported runtimes.GCUserPeerablemethod names.mono.android.*has compatibility implications outside the experimental NativeAOT/trimmable path.