Skip to content
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

Remove support for using Java's WeakReference instead of JNI's weak handles #1257

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

filipnavara
Copy link
Member

Contributes to #1255

@@ -22,7 +22,6 @@ unsafe public class JavaException : Exception, IJavaPeerable
JniObjectReferenceType handle_type;
#pragma warning disable 0169
// Used by JavaInteropGCBridge
IntPtr weak_handle;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

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.

@@ -24,7 +24,6 @@ unsafe public class JavaObject : IJavaPeerable
JniObjectReferenceType handle_type;
#pragma warning disable 0169
// Used by JavaInteropGCBridge
IntPtr weak_handle;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

static mono_bool
take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not changing these method names & related strings, as:

  1. The same names are used in dotnet/android, and consistency is "nice"
  2. The strings are present in tools/logcat-parse unit tests (tests/logcat-parse-Tests), which implies (a) they've been around awhile, and (2) I'm not immediately sure what'll happen to logcat-parse we change them. (Hopefully nothing! But…)

@@ -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);
Copy link
Member

@jonpryor jonpryor Sep 23, 2024

Choose a reason for hiding this comment

The 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 [[maybe_unused]] int weak_ref_kind parameter.) This is nominally "fine" because it's C calling convention, but if we ever accidentally-on-purpose change the calling convention, the difference in number of parameters could cause stack corruption.

This should instead be:

internal static extern int java_interop_gc_bridge_register_hooks (IntPtr bridge, int must_be_one);

Copy link
Member Author

Choose a reason for hiding this comment

The 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…

@@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should assert that weak_ref_kind is one, and bail otherwise:

if (weak_ref_kind != 1) {
    return -1;
}

@@ -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)
Copy link
Member

Choose a reason for hiding this comment

The 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:

% clang++ mu.cc -std=c++17

…but the symbols, they're mangled!

% nm a.out   
0000000100003f80 T __Z3fooi
0000000100000000 T __mh_execute_header
0000000100003f90 T _main

There is no foo symbol, but there is __Z3fooi, the C++ mangled version of foo(int).

My guess -- again, without compiling this PR -- is that src/java-interop will compile, but the resulting native library will not contain a C callable java_interop_gc_bridge_register_hooks, but instead a C++ mangled __Z37java_interop_gc_bridge_register_hooks… symbol, and things will blow up at runtime because the P/Invoke for java_interop_gc_bridge_register_hooks() won't find that symbol.

@filipnavara filipnavara marked this pull request as draft September 24, 2024 04:10
@jonpryor
Copy link
Member

dotnet/android@e98ae9c removes support for debug.mono.wref=java, java.lang.ref.WeakReference, and the weak_handle fields from Java.Lang.Object, Java.Lang.Exception, Java.Interop.JavaObject, and Java.Interop.JavaException.

Development of #1257 can resume, if desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants