Skip to content

Commit 1b1f145

Browse files
[Mono.Android] JNIEnv.FindClass(Type) now uses TypeManager
Context: #9811 The .NET MAUI template + NativeAOT currently crashes with: 02-18 15:59:24.575 12907 12907 E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*) 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.FindClass(Type) + 0x38 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray(IJavaObject[]) + 0x28 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0x94 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Android.Graphics.Drawables.LayerDrawable..ctor(Drawable[] layers) + 0xd4 02-18 15:59:24.575 12907 12907 E AndroidRuntime: at Microsoft.Maui.Platform.MauiRippleDrawableExtensions.UpdateMauiRippleDrawableBackground(View, Paint, IButtonStroke, Func`1, Func`1, Action) + 0x2ac This appears to be related to array usage, such as `LayerDrawable.ctor(Drawable[])` in this example. I can reproduce the same crash using a `ColorStateList.ctor(int[][], int[])` in our NativeAOT "hello world" sample: 02-19 10:45:29.728 28692 28692 E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*) 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Runtime.JNIEnv.FindClass(Type) + 0x38 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0xa8 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at Android.Content.Res.ColorStateList..ctor(Int32[][], Int32[]) + 0xdc 02-19 10:45:29.728 28692 28692 E AndroidRuntime: at NativeAOT.MainActivity.OnCreate(Bundle savedInstanceState) + 0xb8 As an alternative to #9811, we can update `JNIEnv.FindClass(Type)` to go through `TypeManager` instead of using `TypemapManagedToJava`. After this change, the sample works and prints a log message indicating `ColorStateList` is created successfully: 02-19 13:12:25.924 2665 2665 D NativeAOT: MainActivity.OnCreate() ColorStateList: ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[0, 1]]mColors=[0, 1]mDefaultColor=0}
1 parent d012fb8 commit 1b1f145

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

samples/NativeAOT/MainActivity.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Android.Content.Res;
12
using Android.Runtime;
23
using Android.Util;
34
using System.Reflection;
@@ -17,5 +18,9 @@ protected override void OnCreate(Bundle? savedInstanceState)
1718

1819
// Set our view from the "main" layout resource
1920
SetContentView(Resource.Layout.activity_main);
21+
22+
// An example of an Android API that uses a Java array
23+
var list = new ColorStateList (new int[][] { [ 0, 1 ]}, [0, 1]);
24+
Log.Debug ("NativeAOT", "MainActivity.OnCreate() ColorStateList: " + list);
2025
}
2126
}

src/Mono.Android/Android.Runtime/JNIEnv.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,20 @@ public static unsafe IntPtr CreateInstance (Type type, string signature, params
254254

255255
public static IntPtr FindClass (System.Type type)
256256
{
257-
int rank = JavaNativeTypeManager.GetArrayInfo (type, out type);
258257
try {
259-
return FindClass (JavaNativeTypeManager.ToJniName (GetJniName (type), rank));
258+
var sig = JNIEnvInit.androidRuntime?.TypeManager.GetTypeSignature (type) ?? default;
259+
if (!sig.IsValid || sig.SimpleReference == null) {
260+
throw new ArgumentException ($"Could not determine Java type corresponding to `{type.AssemblyQualifiedName}`.", nameof (type));
261+
}
262+
263+
JniObjectReference local_ref = JniEnvironment.Types.FindClass (sig.Name);
264+
IntPtr global_ref = NewGlobalRef (local_ref.Handle);
265+
JniObjectReference.Dispose (ref local_ref);
266+
return global_ref;
260267
} catch (Java.Lang.Throwable e) {
261268
if (!((e is Java.Lang.NoClassDefFoundError) || (e is Java.Lang.ClassNotFoundException)))
262269
throw;
270+
int rank = JavaNativeTypeManager.GetArrayInfo (type, out type);
263271
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $"JNIEnv.FindClass(Type) caught unexpected exception: {e}");
264272
var jni = Java.Interop.TypeManager.GetJniTypeName (type);
265273
if (jni != null) {

0 commit comments

Comments
 (0)