-
Notifications
You must be signed in to change notification settings - Fork 56
Remove support for using Java's WeakReference instead of JNI's weak handles #1257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,6 @@ unsafe public class JavaObject : IJavaPeerable | |
JniObjectReferenceType handle_type; | ||
#pragma warning disable 0169 | ||
// Used by JavaInteropGCBridge | ||
IntPtr weak_handle; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto. |
||
int refs_added; | ||
#pragma warning restore 0169 | ||
#endif // FEATURE_JNIOBJECTREFERENCE_INTPTRS | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,11 +9,6 @@ | |
|
||
namespace Java.Interop { | ||
|
||
enum GCBridgeUseWeakReferenceKind { | ||
Java, | ||
Jni, | ||
} | ||
|
||
class MonoRuntimeValueManager : JniRuntime.JniValueManager { | ||
|
||
#pragma warning disable 0649 | ||
|
@@ -52,7 +47,7 @@ public override void OnSetRuntime (JniRuntime runtime) | |
bridge = IntPtr.Zero; | ||
throw; | ||
} | ||
if (JreNativeMethods.java_interop_gc_bridge_register_hooks (bridge, GCBridgeUseWeakReferenceKind.Jni) < 0) | ||
if (JreNativeMethods.java_interop_gc_bridge_register_hooks (bridge) < 0) | ||
throw new NotSupportedException ("Could not register GC Bridge with Mono!"); | ||
} | ||
|
||
|
@@ -393,7 +388,7 @@ partial class JreNativeMethods { | |
internal static extern int java_interop_gc_bridge_set_current_once (IntPtr bridge); | ||
|
||
[DllImport (JavaInteropLib, CallingConvention=CallingConvention.Cdecl)] | ||
internal static extern int java_interop_gc_bridge_register_hooks (IntPtr bridge, GCBridgeUseWeakReferenceKind weak_ref_kind); | ||
internal static extern int java_interop_gc_bridge_register_hooks (IntPtr bridge); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change introduces a "mismatch" between the native side and the managed side. (Native side has an additional This should instead be: internal static extern int java_interop_gc_bridge_register_hooks (IntPtr bridge, int must_be_one); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was unintentional. I initially kept the parameter as unused and then changed my mind to remove it… |
||
|
||
[DllImport (JavaInteropLib, CallingConvention=CallingConvention.Cdecl)] | ||
internal static extern IntPtr java_interop_gc_bridge_new (IntPtr jvm); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,6 @@ typedef struct MonoJavaGCBridgeInfo { | |
MonoClassField *handle; | ||
MonoClassField *handle_type; | ||
MonoClassField *refs_added; | ||
MonoClassField *weak_handle; | ||
} MonoJavaGCBridgeInfo; | ||
|
||
#define NUM_GC_BRIDGE_TYPES (4) | ||
|
@@ -60,10 +59,6 @@ struct JavaInteropGCBridge { | |
jobject Runtime_instance; | ||
jmethodID Runtime_gc; | ||
|
||
jclass WeakReference_class; | ||
jmethodID WeakReference_init; | ||
jmethodID WeakReference_get; | ||
|
||
jclass GCUserPeerable_class; | ||
jmethodID GCUserPeerable_add; | ||
jmethodID GCUserPeerable_clear; | ||
|
@@ -106,12 +101,9 @@ java_interop_gc_bridge_destroy (JavaInteropGCBridge *bridge) | |
JNIEnv *env = ensure_jnienv (bridge); | ||
if (env != NULL) { | ||
env->DeleteGlobalRef (bridge->Runtime_instance); | ||
env->DeleteGlobalRef (bridge->WeakReference_class); | ||
env->DeleteGlobalRef (bridge->GCUserPeerable_class); | ||
|
||
bridge->Runtime_instance = NULL; | ||
bridge->WeakReference_class = NULL; | ||
|
||
bridge->Runtime_instance = NULL; | ||
bridge->GCUserPeerable_class = NULL; | ||
} | ||
|
||
|
@@ -277,13 +269,6 @@ java_interop_gc_bridge_new (JavaVM *jvm) | |
env->DeleteLocalRef (Runtime_class); | ||
} | ||
|
||
jclass WeakReference_class = env->FindClass ("java/lang/ref/WeakReference"); | ||
if (WeakReference_class != NULL) { | ||
bridge.WeakReference_init = env->GetMethodID (WeakReference_class, "<init>", "(Ljava/lang/Object;)V"); | ||
bridge.WeakReference_get = env->GetMethodID (WeakReference_class, "get", "()Ljava/lang/Object;"); | ||
bridge.WeakReference_class = static_cast<jclass>(lref_to_gref (env, WeakReference_class)); | ||
} | ||
|
||
jclass GCUserPeerable_class = env->FindClass ("net/dot/jni/GCUserPeerable"); | ||
if (GCUserPeerable_class) { | ||
bridge.GCUserPeerable_add = env->GetMethodID (GCUserPeerable_class, "jiAddManagedReference", "(Ljava/lang/Object;)V"); | ||
|
@@ -295,8 +280,7 @@ java_interop_gc_bridge_new (JavaVM *jvm) | |
JavaInteropGCBridge *p = static_cast<JavaInteropGCBridge*>(calloc (1, sizeof (JavaInteropGCBridge))); | ||
|
||
if (p == NULL || bridge.jvm == NULL || | ||
bridge.Runtime_instance == NULL || bridge.Runtime_gc == NULL || | ||
bridge.WeakReference_class == NULL || bridge.WeakReference_init == NULL || bridge.WeakReference_get == NULL) { | ||
bridge.Runtime_instance == NULL || bridge.Runtime_gc == NULL) { | ||
java_interop_gc_bridge_destroy (&bridge); | ||
free (p); | ||
return NULL; | ||
|
@@ -369,10 +353,9 @@ java_interop_gc_bridge_register_bridgeable_type ( | |
info->handle = mono_class_get_field_from_name (info->klass, const_cast<char*> ("handle")); | ||
info->handle_type = mono_class_get_field_from_name (info->klass, const_cast<char*> ("handle_type")); | ||
info->refs_added = mono_class_get_field_from_name (info->klass, const_cast<char*> ("refs_added")); | ||
info->weak_handle = mono_class_get_field_from_name (info->klass, const_cast<char*> ("weak_handle")); | ||
|
||
if (info->klass == NULL || info->handle == NULL || info->handle_type == NULL || | ||
info->refs_added == NULL || info->weak_handle == NULL) | ||
info->refs_added == NULL) | ||
return -1; | ||
bridge->num_bridge_types++; | ||
return 0; | ||
|
@@ -772,72 +755,8 @@ get_gc_bridge_info_for_object (JavaInteropGCBridge *bridge, MonoObject *object) | |
return get_gc_bridge_info_for_class (bridge, mono_object_get_class (object)); | ||
} | ||
|
||
typedef mono_bool (*MonodroidGCTakeRefFunc) (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id); | ||
|
||
static MonodroidGCTakeRefFunc take_global_ref; | ||
static MonodroidGCTakeRefFunc take_weak_global_ref; | ||
|
||
static mono_bool | ||
take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
{ | ||
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj); | ||
if (bridge_info == NULL) | ||
return 0; | ||
|
||
jobject weak; | ||
mono_field_get_value (obj, bridge_info->weak_handle, &weak); | ||
|
||
jobject handle = env->CallObjectMethod (weak, bridge->WeakReference_get); | ||
log_gref (bridge, "*try_take_global_2_1 obj=%p -> wref=%p handle=%p\n", obj, weak, handle); | ||
|
||
if (handle) { | ||
jobject h = env->NewGlobalRef (handle); | ||
env->DeleteLocalRef (handle); | ||
handle = h; | ||
java_interop_gc_bridge_gref_log_new (bridge, weak, get_object_ref_type (env, weak), | ||
handle, get_object_ref_type (env, handle), thread_name, thread_id, "take_global_ref_java"); | ||
} | ||
java_interop_gc_bridge_weak_gref_log_delete (bridge, weak, get_object_ref_type (env, weak), thread_name, thread_id, "take_global_ref_java"); | ||
env->DeleteGlobalRef (weak); | ||
weak = NULL; | ||
mono_field_set_value (obj, bridge_info->weak_handle, &weak); | ||
|
||
mono_field_set_value (obj, bridge_info->handle, &handle); | ||
|
||
int type = JNIGlobalRefType; | ||
mono_field_set_value (obj, bridge_info->handle_type, &type); | ||
|
||
return handle != NULL; | ||
} | ||
|
||
static mono_bool | ||
take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
{ | ||
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj); | ||
if (bridge_info == NULL) | ||
return 0; | ||
|
||
jobject handle; | ||
mono_field_get_value (obj, bridge_info->handle, &handle); | ||
|
||
jobject weaklocal = env->NewObject (bridge->WeakReference_class, bridge->WeakReference_init, handle); | ||
jobject weakglobal = env->NewGlobalRef (weaklocal); | ||
env->DeleteLocalRef (weaklocal); | ||
|
||
log_gref (bridge, "*take_weak_2_1 obj=%p -> wref=%p handle=%p\n", obj, weakglobal, handle); | ||
java_interop_gc_bridge_weak_gref_log_new (bridge, handle, get_object_ref_type (env, handle), | ||
weakglobal, get_object_ref_type (env, weakglobal), thread_name, thread_id, "take_weak_global_ref_2_1_compat"); | ||
|
||
java_interop_gc_bridge_gref_log_delete (bridge, handle, get_object_ref_type (env, handle), thread_name, thread_id, "take_weak_global_ref_2_1_compat"); | ||
env->DeleteGlobalRef (handle); | ||
|
||
mono_field_set_value (obj, bridge_info->weak_handle, &weakglobal); | ||
|
||
return 1; | ||
} | ||
|
||
static mono_bool | ||
take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer not changing these method names & related strings, as:
|
||
take_global_ref (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
{ | ||
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj); | ||
if (bridge_info == NULL) | ||
|
@@ -853,11 +772,11 @@ take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, | |
java_interop_gc_bridge_gref_log_new (bridge, weak, get_object_ref_type (env, weak), | ||
handle, get_object_ref_type (env, handle), | ||
thread_name, thread_id, | ||
"take_global_ref_jni"); | ||
"take_global_ref"); | ||
} | ||
|
||
java_interop_gc_bridge_weak_gref_log_delete (bridge, weak, 'W', | ||
thread_name, thread_id, "take_global_ref_jni"); | ||
thread_name, thread_id, "take_global_ref"); | ||
env->DeleteWeakGlobalRef (weak); | ||
|
||
mono_field_set_value (obj, bridge_info->handle, &handle); | ||
|
@@ -868,7 +787,7 @@ take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, | |
} | ||
|
||
static mono_bool | ||
take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
take_weak_global_ref (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id) | ||
{ | ||
MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj); | ||
if (bridge_info == NULL) | ||
|
@@ -882,10 +801,10 @@ take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject * | |
jobject weak = env->NewWeakGlobalRef (handle); | ||
java_interop_gc_bridge_weak_gref_log_new (bridge, handle, get_object_ref_type (env, handle), | ||
weak, get_object_ref_type (env, weak), | ||
thread_name, thread_id, "take_weak_global_ref_jni"); | ||
thread_name, thread_id, "take_weak_global_ref"); | ||
|
||
java_interop_gc_bridge_gref_log_delete (bridge, handle, get_object_ref_type (env, handle), | ||
thread_name, thread_id, "take_weak_global_ref_jni"); | ||
thread_name, thread_id, "take_weak_global_ref"); | ||
env->DeleteGlobalRef (handle); | ||
|
||
mono_field_set_value (obj, bridge_info->handle, &weak); | ||
|
@@ -1272,7 +1191,7 @@ gc_cross_references (int num_sccs, MonoGCBridgeSCC **sccs, int num_xrefs, MonoGC | |
} | ||
|
||
int | ||
java_interop_gc_bridge_register_hooks (JavaInteropGCBridge *bridge, int weak_ref_kind) | ||
java_interop_gc_bridge_register_hooks (JavaInteropGCBridge *bridge, [[maybe_unused]] int weak_ref_kind) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't tried building this, but I'm kinda shocked at the idea that this would build and/or run, considering that you updated the header file to remove the second parameter. So of course I need to play around… extern "C" {
void foo();
}
void foo([[maybe_unused]] int x) {
}
int main() {
foo(0);
} It compiles without error:
…but the symbols, they're mangled!
There is no My guess -- again, without compiling this PR -- is that |
||
{ | ||
if (bridge == NULL) | ||
return -1; | ||
|
@@ -1284,23 +1203,6 @@ java_interop_gc_bridge_register_hooks (JavaInteropGCBridge *bridge, int weak_ref | |
MonoGCBridgeCallbacks bridge_cbs; | ||
memset (&bridge_cbs, 0, sizeof (bridge_cbs)); | ||
|
||
switch (weak_ref_kind) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should assert that if (weak_ref_kind != 1) {
return -1;
} |
||
case JAVA_INTEROP_GC_BRIDGE_USE_WEAK_REFERENCE_KIND_JAVA: | ||
message = "Using java.lang.ref.WeakReference for JNI Weak References."; | ||
take_global_ref = take_global_ref_java; | ||
take_weak_global_ref = take_weak_global_ref_java; | ||
break; | ||
case JAVA_INTEROP_GC_BRIDGE_USE_WEAK_REFERENCE_KIND_JNI: | ||
message = "Using JNIEnv::NewWeakGlobalRef() for JNI Weak References."; | ||
take_global_ref = take_global_ref_jni; | ||
take_weak_global_ref = take_weak_global_ref_jni; | ||
break; | ||
default: | ||
return -1; | ||
} | ||
|
||
log_gref (mono_bridge, "%s\n", message); | ||
|
||
bridge_cbs.bridge_version = SGEN_BRIDGE_VERSION; | ||
bridge_cbs.bridge_class_kind = gc_bridge_class_kind; | ||
bridge_cbs.is_bridge_object = gc_is_bridge_object; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't remove this field yet, as it's still used by dotnet/android, even if it isn't "used":
Removing it now will result in app startup aborts until dotnet/android is updated to no longer mention
weak_handle
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realize that all this code is duplicated in dotnet/android. I'll return back the field and try to see if we can remove it on dotnet/android side too. The lowest supported API level is 21 for .NET 9, so there doesn't seem to be a valid reason to keep this around.