From 611fe49abeb7e75c3b9484a1d93aacd06749d1b5 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 9 Jun 2025 08:55:14 -0500 Subject: [PATCH 1/6] [Mono.Android] JNI handles are now in a "control block" Originally from: https://github.com/dotnet/android/pull/10125 Context: https://github.com/dotnet/java-interop/pull/1339 These are changes to Mono's GC bridge implementation, such that the same code can be used on both Mono and CoreCLR. The base `JavaObject` type has changes such as: ```diff --[NonSerialized] IntPtr handle; --[NonSerialized] JniObjectReferenceType handle_type; --[NonSerialized] IntPtr weak_handle; --[NonSerialized] int refs_added; ++unsafe JniObjectReferenceControlBlock* jniObjectReferenceControlBlock; ``` And the new `JniObjectReferenceControlBlock` struct is defined as: internal struct JniObjectReferenceControlBlock { public IntPtr handle; public int handle_type; public IntPtr weak_handle; public int refs_added; } * Each `JavaObject` allocation now has a `NativeMemory.AllocZeroed()` call for this struct. * However, we only have to read a single field now using Mono's native embedding API: ```diff --info->handle = mono_class_get_field_from_name (info->klass, const_cast ("handle")); --info->handle_type = mono_class_get_field_from_name (info->klass, const_cast ("handle_type")); --info->refs_added = mono_class_get_field_from_name (info->klass, const_cast ("refs_added")); --info->weak_handle = mono_class_get_field_from_name (info->klass, const_cast ("weak_handle")); ++info->jniObjectReferenceControlBlock = mono_class_get_field_from_name (info->klass, const_cast ("jniObjectReferenceControlBlock")); ``` We are hoping this results in ~the same performance as before, with the flexibility to support multiple GC bridge implementations and runtimes. Co-authored-by: Marek Habersack --- external/Java.Interop | 2 +- src/native/mono/monodroid/monodroid-glue.cc | 17 +-- src/native/mono/monodroid/osbridge.cc | 110 +++++++++++++------- src/native/mono/monodroid/osbridge.hh | 14 ++- 4 files changed, 86 insertions(+), 57 deletions(-) diff --git a/external/Java.Interop b/external/Java.Interop index b1a01072c4e..dcd4ba12646 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit b1a01072c4efe86fad45dddb704160c67bed5ebd +Subproject commit dcd4ba126460e4981e5482a3de0d049632844932 diff --git a/src/native/mono/monodroid/monodroid-glue.cc b/src/native/mono/monodroid/monodroid-glue.cc index d8c722f48f2..9cffb809d0b 100644 --- a/src/native/mono/monodroid/monodroid-glue.cc +++ b/src/native/mono/monodroid/monodroid-glue.cc @@ -793,22 +793,15 @@ MonodroidRuntime::create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks MonodroidRuntime::lookup_bridge_info (MonoClass *klass, const OSBridge::MonoJavaGCBridgeType *type, OSBridge::MonoJavaGCBridgeInfo *info) noexcept { info->klass = klass; - info->handle = mono_class_get_field_from_name (info->klass, const_cast ("handle")); - info->handle_type = mono_class_get_field_from_name (info->klass, const_cast ("handle_type")); - info->refs_added = mono_class_get_field_from_name (info->klass, const_cast ("refs_added")); - info->key_handle = mono_class_get_field_from_name (info->klass, const_cast ("key_handle")); + info->jniObjectReferenceControlBlock = mono_class_get_field_from_name (info->klass, const_cast("jniObjectReferenceControlBlock")); - // key_handle is optional, as Java.Interop.JavaObject doesn't currently have it - if (info->klass == nullptr || info->handle == nullptr || info->handle_type == nullptr || info->refs_added == nullptr) { + if (info->klass == nullptr || info->jniObjectReferenceControlBlock == nullptr) { Helpers::abort_application ( - Util::monodroid_strdup_printf ( - "The type `%s.%s` is missing required instance fields! handle=%p handle_type=%p refs_added=%p key_handle=%p", + std::format ( + "The type `{}.{} is missing required instance fields! jniObjectReferenceControlBlock={:p}", type->_namespace, type->_typename, - info->handle, - info->handle_type, - info->refs_added, - info->key_handle + static_cast(info->jniObjectReferenceControlBlock) ) ); } diff --git a/src/native/mono/monodroid/osbridge.cc b/src/native/mono/monodroid/osbridge.cc index 919506d3fda..4c8cd6a77a8 100644 --- a/src/native/mono/monodroid/osbridge.cc +++ b/src/native/mono/monodroid/osbridge.cc @@ -42,9 +42,6 @@ const uint32_t OSBridge::NUM_GC_BRIDGE_TYPES = NUM_XA_GC_BRIDGE_TYPES + NUM_J OSBridge::MonoJavaGCBridgeInfo OSBridge::mono_java_gc_bridge_info [NUM_GC_BRIDGE_TYPES]; OSBridge::MonoJavaGCBridgeInfo OSBridge::empty_bridge_info = { - nullptr, - nullptr, - nullptr, nullptr, nullptr }; @@ -76,9 +73,13 @@ OSBridge::clear_mono_java_gc_bridge_info () for (uint32_t c = 0; c < NUM_GC_BRIDGE_TYPES; c++) { MonoJavaGCBridgeInfo *info = &mono_java_gc_bridge_info [c]; info->klass = nullptr; - info->handle = nullptr; - info->handle_type = nullptr; - info->refs_added = nullptr; + auto control_block = reinterpret_cast(info->jniObjectReferenceControlBlock); + if (control_block == nullptr) [[unlikely]] { + continue; + } + control_block->handle = nullptr; + control_block->handle_type = 0; + control_block->refs_added = 0; } } @@ -102,6 +103,19 @@ OSBridge::get_gc_bridge_index (MonoClass *klass) : -1; } +OSBridge::JniObjectReferenceControlBlock* +OSBridge::get_gc_control_block_for_object (MonoObject *obj) +{ + MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (obj); + if (bridge_info == nullptr) { + return nullptr; + } + + JniObjectReferenceControlBlock *control_block = nullptr; + mono_field_get_value (obj, bridge_info->jniObjectReferenceControlBlock, &control_block); + return control_block; +} + OSBridge::MonoJavaGCBridgeInfo * OSBridge::get_gc_bridge_info_for_class (MonoClass *klass) { @@ -459,11 +473,12 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) jobject handle, weak; int type = JNIGlobalRefType; - MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (obj); - if (bridge_info == nullptr) + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); + if (control_block == nullptr) { return 0; + } - mono_field_get_value (obj, bridge_info->handle, &weak); + mono_field_get_value (obj, reinterpret_cast(control_block->handle), &weak); handle = env->NewGlobalRef (weak); if (gref_log) { fprintf (gref_log, "*try_take_global obj=%p -> wref=%p handle=%p\n", obj, weak, handle); @@ -476,8 +491,8 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) " at [[gc:take_global_ref_jni]]", 0); } else if (Logger::gc_spew_enabled ()) [[unlikely]] { void *key_handle = nullptr; - if (bridge_info->key_handle) { - mono_field_get_value (obj, bridge_info->key_handle, &key_handle); + if (control_block->weak_handle) { + mono_field_get_value (obj, reinterpret_cast(control_block->weak_handle), &key_handle); } MonoClass *klass = mono_object_get_class (obj); @@ -491,8 +506,8 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) free (message); } - mono_field_set_value (obj, bridge_info->handle, &handle); - mono_field_set_value (obj, bridge_info->handle_type, &type); + mono_field_set_value (obj, reinterpret_cast(control_block->handle), &handle); + mono_field_set_value (obj, reinterpret_cast(control_block->handle_type), &type); _monodroid_weak_gref_delete (weak, get_object_ref_type (env, weak), "finalizer", gettid (), " at [[gc:take_global_ref_jni]]", 0); @@ -507,11 +522,12 @@ OSBridge::take_weak_global_ref_jni (JNIEnv *env, MonoObject *obj) jobject handle, weak; int type = JNIWeakGlobalRefType; - MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (obj); - if (bridge_info == nullptr) + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); + if (control_block == nullptr) { return 0; + } - mono_field_get_value (obj, bridge_info->handle, &handle); + mono_field_get_value (obj, reinterpret_cast(control_block->handle), &handle); if (gref_log) { fprintf (gref_log, "*take_weak obj=%p; handle=%p\n", obj, handle); fflush (gref_log); @@ -522,8 +538,8 @@ OSBridge::take_weak_global_ref_jni (JNIEnv *env, MonoObject *obj) weak, get_object_ref_type (env, weak), "finalizer", gettid (), " at [[gc:take_weak_global_ref_jni]]", 0); - mono_field_set_value (obj, bridge_info->handle, &weak); - mono_field_set_value (obj, bridge_info->handle_type, &type); + mono_field_set_value (obj, reinterpret_cast(control_block->handle), &weak); + mono_field_set_value (obj, reinterpret_cast(control_block->handle_type), &type); _monodroid_gref_log_delete (handle, get_object_ref_type (env, handle), "finalizer", gettid (), " at [[gc:take_weak_global_ref_jni]]", 0); @@ -558,13 +574,23 @@ OSBridge::gc_bridge_class_kind (MonoClass *klass) mono_bool OSBridge::gc_is_bridge_object (MonoObject *object) { - void *handle; + if (object == nullptr) [[unlikely]] { + log_debug (LOG_GC, "gc_is_bridge_object was passed a NULL object pointer"); + return FALSE; + } - MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (object); - if (bridge_info == nullptr) - return 0; + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (object); + if (control_block == nullptr) { + return FALSE; + } + + if (control_block->handle == nullptr) { + log_warn (LOG_GC, "gc_is_bridge_object: control block's handle is NULL"); + return FALSE; + } - mono_field_get_value (object, bridge_info->handle, &handle); + void *handle; + mono_field_get_value (object, reinterpret_cast(control_block->handle), &handle); if (handle == nullptr) { #if DEBUG MonoClass *mclass = mono_object_get_class (object); @@ -574,10 +600,10 @@ OSBridge::gc_is_bridge_object (MonoObject *object) optional_string (mono_class_get_name (mclass)) ); #endif - return 0; + return FALSE; } - return 1; + return TRUE; } // Add a reference from an IGCUserPeer jobject to another jobject @@ -604,10 +630,11 @@ mono_bool OSBridge::load_reference_target (OSBridge::AddReferenceTarget target, OSBridge::MonoJavaGCBridgeInfo** bridge_info, jobject *handle) { if (target.is_mono_object) { - *bridge_info = get_gc_bridge_info_for_object (target.obj); - if (!*bridge_info) + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (target.obj); + if (control_block == nullptr) { return FALSE; - mono_field_get_value (target.obj, (*bridge_info)->handle, handle); + } + mono_field_get_value (target.obj, reinterpret_cast(control_block->handle), handle); } else { *handle = target.jobj; } @@ -649,7 +676,11 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri // Java temporaries do not need this because the entire GCUserPeer is discarded. if (success && target.is_mono_object) { int ref_val = 1; - mono_field_set_value (target.obj, bridge_info->refs_added, &ref_val); + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (target.obj); + if (control_block == nullptr) { + return FALSE; + } + mono_field_set_value (target.obj, reinterpret_cast(control_block->refs_added), &ref_val); } #if DEBUG @@ -867,14 +898,13 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri sccs [i]->is_alive = 0; for (j = 0; j < sccs [i]->num_objs; j++) { - MonoJavaGCBridgeInfo *bridge_info; - obj = sccs [i]->objs [j]; - bridge_info = get_gc_bridge_info_for_object (obj); - if (bridge_info == nullptr) + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); + if (control_block == nullptr) { continue; - mono_field_get_value (obj, bridge_info->handle, &jref); + } + mono_field_get_value (obj, reinterpret_cast(control_block->handle), &jref); if (jref) { alive++; if (j > 0) { @@ -884,7 +914,7 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri ); } sccs [i]->is_alive = 1; - mono_field_get_value (obj, bridge_info->refs_added, &refs_added); + mono_field_get_value (obj, (MonoClassField*) control_block->refs_added, &refs_added); if (refs_added) { jclass java_class = env->GetObjectClass (jref); clear_method_id = env->GetMethodID (java_class, "monodroidClearReferences", "()V"); @@ -951,13 +981,13 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre for (j = 0; j < sccs [i]->num_objs; ++j) { MonoObject *obj = sccs [i]->objs [j]; - MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (obj); + JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); jobject handle = 0; void *key_handle = nullptr; - if (bridge_info != nullptr) { - mono_field_get_value (obj, bridge_info->handle, &handle); - if (bridge_info->key_handle != nullptr) { - mono_field_get_value (obj, bridge_info->key_handle, &key_handle); + if (control_block != nullptr) { + mono_field_get_value (obj, reinterpret_cast(control_block->handle), &handle); + if (control_block->weak_handle != nullptr) { + mono_field_get_value (obj, reinterpret_cast(control_block->weak_handle), &key_handle); } } MonoClass *klass = mono_object_get_class (obj); diff --git a/src/native/mono/monodroid/osbridge.hh b/src/native/mono/monodroid/osbridge.hh index 46f4af69ef8..f439a57aedd 100644 --- a/src/native/mono/monodroid/osbridge.hh +++ b/src/native/mono/monodroid/osbridge.hh @@ -37,10 +37,15 @@ namespace xamarin::android::internal struct MonoJavaGCBridgeInfo { MonoClass *klass; - MonoClassField *handle; - MonoClassField *handle_type; - MonoClassField *refs_added; - MonoClassField *key_handle; + MonoClassField *jniObjectReferenceControlBlock; + }; + + struct JniObjectReferenceControlBlock + { + jobject handle; + int handle_type; + jobject weak_handle; + int refs_added; }; // add_reference can work with objects which are either MonoObjects with java peers, or raw jobjects @@ -127,6 +132,7 @@ namespace xamarin::android::internal private: int get_gc_bridge_index (MonoClass *klass); + JniObjectReferenceControlBlock* get_gc_control_block_for_object (MonoObject *obj); MonoJavaGCBridgeInfo* get_gc_bridge_info_for_class (MonoClass *klass); MonoJavaGCBridgeInfo* get_gc_bridge_info_for_object (MonoObject *object); char get_object_ref_type (JNIEnv *env, void *handle); From e070029f588d31f6b50d0142087d2d51a93ca28d Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 9 Jun 2025 10:48:15 -0500 Subject: [PATCH 2/6] Update Java.Interop.xml --- .../PreserveLists/Java.Interop.xml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Java.Interop.xml b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Java.Interop.xml index 7ee32570100..3140d548e73 100644 --- a/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Java.Interop.xml +++ b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/Java.Interop.xml @@ -2,14 +2,10 @@ - - - + - - - + From 00fda8af7fde6dfd806c9d1087d758f8f44f02cc Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 9 Jun 2025 14:01:23 -0500 Subject: [PATCH 3/6] Update Java.Interop --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index dcd4ba12646..06a6a1e00a2 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit dcd4ba126460e4981e5482a3de0d049632844932 +Subproject commit 06a6a1e00a20dc4762bae41724bc289c4a98eef2 From 33dec60ed5bcf6c51f1b81240bef1f0605f4e3e4 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Wed, 11 Jun 2025 18:37:30 +0200 Subject: [PATCH 4/6] Fix SIGSEGV when using the new control block We were using it incorrectly - there's no need to fetch/set values of managed object fields. The correct thing to do is to read/write them on the control block itself. --- src/native/mono/monodroid/osbridge.cc | 50 ++++++++++++++------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/native/mono/monodroid/osbridge.cc b/src/native/mono/monodroid/osbridge.cc index 4c8cd6a77a8..938236841eb 100644 --- a/src/native/mono/monodroid/osbridge.cc +++ b/src/native/mono/monodroid/osbridge.cc @@ -79,6 +79,7 @@ OSBridge::clear_mono_java_gc_bridge_info () } control_block->handle = nullptr; control_block->handle_type = 0; + control_block->weak_handle = nullptr; control_block->refs_added = 0; } } @@ -470,7 +471,6 @@ OSBridge::monodroid_disable_gc_hooks () mono_bool OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) { - jobject handle, weak; int type = JNIGlobalRefType; JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); @@ -478,8 +478,8 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) return 0; } - mono_field_get_value (obj, reinterpret_cast(control_block->handle), &weak); - handle = env->NewGlobalRef (weak); + jobject weak = control_block->handle; + jobject handle = env->NewGlobalRef (weak); if (gref_log) { fprintf (gref_log, "*try_take_global obj=%p -> wref=%p handle=%p\n", obj, weak, handle); fflush (gref_log); @@ -491,8 +491,8 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) " at [[gc:take_global_ref_jni]]", 0); } else if (Logger::gc_spew_enabled ()) [[unlikely]] { void *key_handle = nullptr; - if (control_block->weak_handle) { - mono_field_get_value (obj, reinterpret_cast(control_block->weak_handle), &key_handle); + if (control_block->weak_handle != nullptr) { + key_handle = control_block->weak_handle; } MonoClass *klass = mono_object_get_class (obj); @@ -506,8 +506,8 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) free (message); } - mono_field_set_value (obj, reinterpret_cast(control_block->handle), &handle); - mono_field_set_value (obj, reinterpret_cast(control_block->handle_type), &type); + control_block->handle = handle; + control_block->handle_type = type; _monodroid_weak_gref_delete (weak, get_object_ref_type (env, weak), "finalizer", gettid (), " at [[gc:take_global_ref_jni]]", 0); @@ -519,7 +519,6 @@ OSBridge::take_global_ref_jni (JNIEnv *env, MonoObject *obj) mono_bool OSBridge::take_weak_global_ref_jni (JNIEnv *env, MonoObject *obj) { - jobject handle, weak; int type = JNIWeakGlobalRefType; JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (obj); @@ -527,19 +526,19 @@ OSBridge::take_weak_global_ref_jni (JNIEnv *env, MonoObject *obj) return 0; } - mono_field_get_value (obj, reinterpret_cast(control_block->handle), &handle); + jobject handle = control_block->handle; if (gref_log) { fprintf (gref_log, "*take_weak obj=%p; handle=%p\n", obj, handle); fflush (gref_log); } - weak = env->NewWeakGlobalRef (handle); + jobject weak = env->NewWeakGlobalRef (handle); _monodroid_weak_gref_new (handle, get_object_ref_type (env, handle), weak, get_object_ref_type (env, weak), "finalizer", gettid (), " at [[gc:take_weak_global_ref_jni]]", 0); - mono_field_set_value (obj, reinterpret_cast(control_block->handle), &weak); - mono_field_set_value (obj, reinterpret_cast(control_block->handle_type), &type); + control_block->handle = weak; + control_block->handle_type = type; _monodroid_gref_log_delete (handle, get_object_ref_type (env, handle), "finalizer", gettid (), " at [[gc:take_weak_global_ref_jni]]", 0); @@ -589,9 +588,7 @@ OSBridge::gc_is_bridge_object (MonoObject *object) return FALSE; } - void *handle; - mono_field_get_value (object, reinterpret_cast(control_block->handle), &handle); - if (handle == nullptr) { + if (control_block->handle == nullptr) { #if DEBUG MonoClass *mclass = mono_object_get_class (object); log_info (LOG_GC, @@ -629,12 +626,17 @@ OSBridge::add_reference_jobject (JNIEnv *env, jobject handle, jobject reffed_han mono_bool OSBridge::load_reference_target (OSBridge::AddReferenceTarget target, OSBridge::MonoJavaGCBridgeInfo** bridge_info, jobject *handle) { + if (handle == nullptr) [[unlikely]] { + return FALSE; + } + if (target.is_mono_object) { JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (target.obj); if (control_block == nullptr) { return FALSE; } - mono_field_get_value (target.obj, reinterpret_cast(control_block->handle), handle); + + *handle = control_block->handle; } else { *handle = target.jobj; } @@ -675,12 +677,11 @@ OSBridge::add_reference (JNIEnv *env, OSBridge::AddReferenceTarget target, OSBri // Flag MonoObjects so they can be cleared in gc_cleanup_after_java_collection. // Java temporaries do not need this because the entire GCUserPeer is discarded. if (success && target.is_mono_object) { - int ref_val = 1; JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (target.obj); if (control_block == nullptr) { return FALSE; } - mono_field_set_value (target.obj, reinterpret_cast(control_block->refs_added), &ref_val); + control_block->refs_added = 1; } #if DEBUG @@ -904,8 +905,9 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri if (control_block == nullptr) { continue; } - mono_field_get_value (obj, reinterpret_cast(control_block->handle), &jref); - if (jref) { + + jref = control_block->handle; + if (jref != nullptr) { alive++; if (j > 0) { abort_unless ( @@ -914,8 +916,8 @@ OSBridge::gc_cleanup_after_java_collection (JNIEnv *env, int num_sccs, MonoGCBri ); } sccs [i]->is_alive = 1; - mono_field_get_value (obj, (MonoClassField*) control_block->refs_added, &refs_added); - if (refs_added) { + refs_added = control_block->refs_added; + if (refs_added != 0) { jclass java_class = env->GetObjectClass (jref); clear_method_id = env->GetMethodID (java_class, "monodroidClearReferences", "()V"); env->DeleteLocalRef (java_class); @@ -985,9 +987,9 @@ OSBridge::gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xre jobject handle = 0; void *key_handle = nullptr; if (control_block != nullptr) { - mono_field_get_value (obj, reinterpret_cast(control_block->handle), &handle); + handle = control_block->handle; if (control_block->weak_handle != nullptr) { - mono_field_get_value (obj, reinterpret_cast(control_block->weak_handle), &key_handle); + key_handle = control_block->weak_handle; } } MonoClass *klass = mono_object_get_class (obj); From 9f3d6f5f4e5e6797a63b5bbef28dc99a85bc8e7d Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 11 Jun 2025 15:53:50 -0500 Subject: [PATCH 5/6] Update Java.Interop --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index a29fe5e4580..f8b62a68064 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit a29fe5e45800e573b9f42377af49c1e1acc37a51 +Subproject commit f8b62a6806470b61b1f88ea79efd50be549ffea2 From 86ab02262f55efc9c0749234ebb3f4d124564e4d Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 12 Jun 2025 11:18:22 -0500 Subject: [PATCH 6/6] Update Java.Interop --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index f8b62a68064..40d27ebf3e4 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit f8b62a6806470b61b1f88ea79efd50be549ffea2 +Subproject commit 40d27ebf3e492e77bb04c111f8a257b82e4f41b0