Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public class JavaInteropRuntime {
private JavaInteropRuntime() {
}

public static native void init();
public static native void init(ClassLoader classLoader);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}");
}

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

Copilot AI May 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider extracting the magic number 5000 into a named constant for improved clarity and maintainability in test code.

Suggested change
thread.Join (5000);
thread.Join (ThreadJoinTimeoutMs);

Copilot uses AI. Check for mistakes.
Assert.IsNull (ex, $"Failed to register instance of a class on new thread: {ex}");
}

[Test]
public void ThreadReuse ()
{
Expand Down Expand Up @@ -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")]
Expand Down
Loading