diff --git a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs index 982f1c5a210..340078864e8 100644 --- a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs +++ b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs @@ -31,7 +31,7 @@ static void JNI_OnUnload (IntPtr vm, IntPtr reserved) // symbol name from `$(IntermediateOutputPath)obj/Release/osx-arm64/h-classes/net_dot_jni_hello_JavaInteropRuntime.h` [UnmanagedCallersOnly (EntryPoint="Java_net_dot_jni_nativeaot_JavaInteropRuntime_init")] - static void init (IntPtr jnienv, IntPtr klass) + static void init (IntPtr jnienv, IntPtr klass, IntPtr classLoader) { JniTransition transition = default; try { @@ -41,6 +41,7 @@ static void init (IntPtr jnienv, IntPtr klass) var typeManager = new ManagedTypeManager (); var options = new NativeAotRuntimeOptions { EnvironmentPointer = jnienv, + ClassLoader = new JniObjectReference (classLoader), TypeManager = typeManager, ValueManager = new ManagedValueManager (), UseMarshalMemberBuilder = false, diff --git a/src/Xamarin.Android.Build.Tasks/Resources/JavaInteropRuntime.java b/src/Xamarin.Android.Build.Tasks/Resources/JavaInteropRuntime.java index cb0474682f9..194c8ddb03d 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/JavaInteropRuntime.java +++ b/src/Xamarin.Android.Build.Tasks/Resources/JavaInteropRuntime.java @@ -11,5 +11,5 @@ public class JavaInteropRuntime { private JavaInteropRuntime() { } - public static native void init(); + public static native void init(ClassLoader classLoader); } diff --git a/src/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java b/src/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java index a3acd8935af..f5db2335339 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java +++ b/src/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java @@ -37,8 +37,10 @@ public void attachInfo(android.content.Context context, android.content.pm.Provi Log.e(TAG, "Failed to set environment variables", e); } + ClassLoader loader = context.getClassLoader (); + // Initialize .NET runtime - JavaInteropRuntime.init(); + JavaInteropRuntime.init(loader); // NOTE: only required for custom applications ApplicationRegistration.registerApplications(); super.attachInfo (context, info); diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs b/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs index c97a8d6e1d3..a563f56fd3a 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs @@ -44,7 +44,7 @@ public void TestMyPaintColor () public void RegisterTypeOnNewNativeThread () { Java.Lang.JavaSystem.LoadLibrary ("reuse-threads"); - int ret = rt_register_type_on_new_thread ("from.NewThreadOne", Application.Context.ClassLoader.Handle); + int ret = rt_register_type_on_new_thread ("from.NewNativeThreadOne", Application.Context.ClassLoader.Handle); Assert.AreEqual (0, ret, $"Java type registration on a new thread failed with code {ret}"); } @@ -57,6 +57,23 @@ public void RegisterTypeOnNewJavaThread () Assert.AreNotEqual (null, thread.Instance, "Failed to register instance of a class on new thread"); } + [Test] + public void RegisterTypeOnNewManagedThread () + { + Exception? ex = null; + var thread = new System.Threading.Thread (() => { + try { + using var instance = new RegisterMeOnNewManagedThreadOne (); + } + catch (Exception e) { + ex = e; + } + }); + thread.Start (); + thread.Join (5000); + Assert.IsNull (ex, $"Failed to register instance of a class on new thread: {ex}"); + } + [Test] public void ThreadReuse () { @@ -459,8 +476,12 @@ public void DoNotLeakWeakReferences () } } - [Register ("from/NewThreadOne")] - class RegisterMeOnNewThreadOne : Java.Lang.Object + [Register ("from/NewNativeThreadOne")] + class RegisterMeOnNewNativeThreadOne : Java.Lang.Object + {} + + [Register ("from/NewManagedThreadOne")] + class RegisterMeOnNewManagedThreadOne : Java.Lang.Object {} [Register ("from/NewThreadTwo")]