You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Java.Interop] JNI handles are now in a "control block"
Context: dotnet/runtime#114184
Context: dotnet/android#10125
Context: dotnet/android#10125 (comment)
Part of adding a GC bridge to CoreCLR are the new APIs:
namespace System.Runtime.InteropServices.Java;
public struct ComponentCrossReference {
public nint SourceGroupIndex, DestinationGroupIndex;
}
public unsafe struct StronglyConnectedComponent {
public nint Count;
public IntPtr* Context;
}
public static partial class JavaMarshal {
public static unsafe void Initialize(
delegate* unmanaged<
System.IntPtr, // sccsLen
StronglyConnectedComponent*, // sccs
System.IntPtr, // ccrsLen
ComponentCrossReference*, // ccrs
void> markCrossReferences);
public static GCHandle CreateReferenceTrackingHandle(object obj, IntPtr context);
public static IntPtr GetContext(GCHandle obj);
}
Of note is the "data flow" of `context`:
* `JavaMarshal.CreateReferenceTrackingHandle()` has a "`context`"
parameter.
* The `context` parameter to
`JavaMarshal.CreateReferenceTrackingHandle()` is the return value
of `JavaMarshal.GetContext()`
* The `context` parameter to
`JavaMarshal.CreateReferenceTrackingHandle()` is stored within
`StronglyConnectedComponent.Context`.
* The `markCrossReferences` parameter of `JavaMarshal.Initialize()`
is called by the GC bridge and given a native array of
`StronglyConnectedComponent` instances, which contains `Context`.
The short of it is that the proposed GC bridge doesn't contain direct
access to the `IJavaPeerable` instances in play. Instead, it has
access to "context" which must contain the JNI Object Reference
information that the `markCrossReferences` callback needs access to.
Furthermore, the `context` pointer value *cannot change*, i.e. it
needs to be a native pointer value a'la **malloc**(3), ***not*** a
value which can be moved by the GC. (The *contents* can change; the
pointer value cannot.))
While we're still prototyping this, what we currently believe we need
is the JNI object reference, JNI object reference type, and (maybe?)
the JNI Weak Global Reference value and "refs added" values.
Update `IJavaPeerable` to add a `JniObjectReferenceControlBlock`
property which can be used as the `context` parameter:
partial interface IJavaPeerable {
IntPtr JniObjectReferenceControlBlock => 0;
}
This supports usage of:
IJavaPeerable value = …
GCHandle handle = JavaMarshal.CreateReferenceTrackingHandle(
value,
value.JniObjectReferenceControlBlock
);
0 commit comments