-
Notifications
You must be signed in to change notification settings - Fork 538
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
[Mono.Android] add fallback for TypemapManagedToJava
#9811
Conversation
const string FeatureSwitchPrefix = "Android.Runtime.RuntimeFeature."; | ||
|
||
[FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (UseReflectionForManagedToJava)}")] | ||
internal static bool UseReflectionForManagedToJava { get; } = |
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.
Taking suggestions on a better name than UseReflectionForManagedToJava
...
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 would prefer that we not need the linker switch, and I think my earlier suggestion would prevent the need for this linker switch.
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 To fix this: * Introduce a new `Android.Runtime.RuntimeFeature.UseReflectionForManagedToJava` feature switch * If the switch is toggled, call `JavaNativeTypeManager.ToJniName(System.Type)` instead of `TypemapManagedToJava()`. * Toggle the feature switch for NativeAOT. In the future, we may enable this switch as a stopgap for getting other runtimes to launch successfully. To reduce confusion, I also removed the managed side of `JNIEnvInit.IsRunningOnDesktop`, which was support for the Android designer. It was using the exact same fallback after attempting `TypemapManagedToJava()`. In a future PR, we could probably also remove the native C/C++ side of this flag.
8c14733
to
203ce44
Compare
if (RuntimeFeature.UseReflectionForManagedToJava) { | ||
return JavaNativeTypeManager.ToJniName (type); | ||
} |
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 could actually move this check inside TypemapManagedToJava()
, is that actually better?
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 think you shouldn't be touching this file at all, because we now have a NativeAotTypeManager
(7a772f0, 70bd636) and the problem is we're not using it.
As suggested on Discord, I think we instead want to update the codepath which is hitting GetJniName()
/TypemapManagedToJava()
in the first place, by updating JNIEnv.FindClass()
to call:
var sig = JNIEnvInit.androidRuntime.TypeManager.GetTypeSignature(type);
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'll try this to see if that is even simpler.
@@ -13,6 +13,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. | |||
<PropertyGroup> | |||
<_AndroidRuntimePackRuntime>NativeAOT</_AndroidRuntimePackRuntime> | |||
<AndroidCodegenTarget Condition=" '$(AndroidCodegenTarget)' == '' ">JavaInterop1</AndroidCodegenTarget> | |||
<_AndroidUseReflectionForManagedToJava Condition=" '$(_AndroidUseReflectionForManagedToJava)' == '' ">true</_AndroidUseReflectionForManagedToJava> |
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.
Could this be set somewhere where it is not just NativeAOT specific and default to True when '$(_AndroidRuntime)' != 'MonoVM'
?
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 can put the same thing here:
Lines 10 to 13 in 66ffd38
<!-- Default property values for CoreCLR --> | |
<PropertyGroup> | |
<_AndroidRuntimePackRuntime>CoreCLR</_AndroidRuntimePackRuntime> | |
</PropertyGroup> |
If we for sure will need it at first, I can add it.
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}
Changes: dotnet/java-interop@f30e420...9dea87d * dotnet/java-interop@9dea87dc: [Java.Interop] .GetTypeSignature() supports unsigned types (dotnet/java-interop#1312) * dotnet/java-interop@1cfb4f4d: [generator] Add support for emitting `[UnsupportedOSPlatform]` (dotnet/java-interop#1307) Context: #9811 The .NET MAUI template + NativeAOT currently crashes with: E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*) E AndroidRuntime: at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c E AndroidRuntime: at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18 E AndroidRuntime: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104 E AndroidRuntime: at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c E AndroidRuntime: at Android.Runtime.JNIEnv.FindClass(Type) + 0x38 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray(IJavaObject[]) + 0x28 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0x94 E AndroidRuntime: at Android.Graphics.Drawables.LayerDrawable..ctor(Drawable[] layers) + 0xd4 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 `samples/NativeAOT`: E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*) E AndroidRuntime: at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c E AndroidRuntime: at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18 E AndroidRuntime: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104 E AndroidRuntime: at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c E AndroidRuntime: at Android.Runtime.JNIEnv.FindClass(Type) + 0x38 E AndroidRuntime: at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0xa8 E AndroidRuntime: at Android.Content.Res.ColorStateList..ctor(Int32[][], Int32[]) + 0xdc E AndroidRuntime: at NativeAOT.MainActivity.OnCreate(Bundle savedInstanceState) + 0xb8 Update `JNIEnv.FindClass(Type)` to go through `TypeManager` instead of using `TypemapManagedToJava`. This avoids the P/Invoke which is causing the crash (f800c1a). Note that we can't directly use `JniRuntime.JniTypeManager.GetTypeSignature()`, as the previous use of `JavaNativeTypeManager.ToJniName(Type)` would default to using `java/lang/Object` if there was no typemap entry for `type`. After this change, the sample works and prints a log message indicating `ColorStateList` is created successfully: D NativeAOT: MainActivity.OnCreate() ColorStateList: ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[0, 1]]mColors=[0, 1]mDefaultColor=0}
I will keep this around, if we ever need to bring it back. We may not need it due to: But it is a good example of setting up a trimmer feature switch. |
The .NET MAUI template + NativeAOT currently crashes with:
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:To fix this:
Introduce a new
Android.Runtime.RuntimeFeature.UseReflectionForManagedToJava
feature switchIf the switch is toggled, call
JavaNativeTypeManager.ToJniName(System.Type)
instead ofTypemapManagedToJava()
.Toggle the feature switch for NativeAOT.
In the future, we may enable this switch as a stopgap for getting other runtimes to launch successfully.
To reduce confusion, I also removed the managed side of
JNIEnvInit.IsRunningOnDesktop
, which was support for the Android designer. It was using the exact same fallback after attemptingTypemapManagedToJava()
. In a future PR, we could probably also remove the native C/C++ side of this flag.