runtime: AOT+LLVM throws for `Enum.GetUnderlyingType()` on Android in .NET 7
Description
Our Mono.Android-Tests
project crashes on startup with:
05-05 15:19:34.429 4929 4929 F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Type provided must be an Enum. Arg_ParamName_Name, enumType
05-05 15:19:34.429 4929 4929 F mono-rt : at System.Enum.InternalGetUnderlyingType(RuntimeType enumType)
05-05 15:19:34.429 4929 4929 F mono-rt : at System.RuntimeType.GetEnumUnderlyingType()
05-05 15:19:34.429 4929 4929 F mono-rt : at System.Enum.GetUnderlyingType(Type enumType)
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Interop.JniRuntime.JniTypeManager.GetUnderlyingType(Type , Int32& )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Lang.Error..ctor(String )
05-05 15:19:34.429 4929 4929 F mono-rt : at Android.Runtime.JavaProxyThrowable..ctor(Exception )
05-05 15:19:34.429 4929 4929 F mono-rt : at Java.Lang.Throwable.FromException(Exception )
05-05 15:19:34.429 4929 4929 F mono-rt : at Android.Runtime.AndroidEnvironment.UnhandledException(Exception e)
05-05 15:19:34.429 4929 4929 F mono-rt : at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V , IntPtr , IntPtr , IntPtr )
This looks oddly familiar to a related issue in mono/mono: https://github.com/xamarin/xamarin-android/issues/1842
Looking at the underlying code, I think it throws here:
Reproduction Steps
Build a .NET 7 Release
app with -p:EnableLLVM=true
.
Expected behavior
Use of -p:EnableLLVM=true
on Android doesn’t crash on startup.
Actual behavior
Use of -p:EnableLLVM=true
crashes on startup on Android.
Regression?
This project appears to be working in .NET 6.
Known Workarounds
Disable LLVM.
Configuration
.NET 7.0.100-preview.4.22174.1 c7afae6936bf80239aa93bfd3b6f68513d9876d4 .NET runtime 7.0.0-preview.4.22172.7 c5d40c9e703fd257db1b26ef4fd1399bbae73ab0
Other information
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 18 (17 by maintainers)
Commits related to this issue
- Bump to dotnet/installer/main@c7afae69 7.0.100-preview.4.22174.1 (#6598) Context: https://github.com/dotnet/runtime/issues/56989 Context: https://github.com/dotnet/runtime/issues/68734 Context: htt... — committed to xamarin/xamarin-android by dotnet-maestro[bot] 2 years ago
- [tests] enable .NET 7 LLVM tests without Profiled AOT Context: https://github.com/dotnet/runtime/issues/68914 We found that the issue with LLVM only occurs when using Profiled AOT. This is enabled ... — committed to jonathanpeppers/xamarin-android by jonathanpeppers 2 years ago
- [tests] enable .NET 7 LLVM tests without Profiled AOT Context: https://github.com/dotnet/runtime/issues/68914 We found that the issue with LLVM only occurs when using Profiled AOT. This is enabled ... — committed to jonathanpeppers/xamarin-android by jonathanpeppers 2 years ago
- [tests] enable .NET 7 LLVM tests without Profiled AOT Context: https://github.com/dotnet/runtime/issues/68914 We found that the issue with LLVM only occurs when using Profiled AOT. This is enabled ... — committed to jonathanpeppers/xamarin-android by jonathanpeppers 2 years ago
- [tests] enable .NET 7 LLVM tests without Profiled AOT Context: https://github.com/dotnet/runtime/issues/68914 We found that the issue with LLVM only occurs when using Profiled AOT. This is enabled ... — committed to jonathanpeppers/xamarin-android by jonathanpeppers 2 years ago
What’s “odd” about this stack trace is that it makes no sense.
It starts with the
JavaProxyThrowable
constructor, which chains to theJava.Lang.Error
constructor, which does:i.e. the
System.Type
instance will betypeof(JavaProxyThrowable)
.We then hit
JniPeerMembers.JniInstanceMethods.StartCreateInstance()
: https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs#L97-L112which calls
GetConstructorsForType()
: https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs#L70-L82declaringType
istypeof(JavaProxyThrowable)
.DeclaringType
istypeof(Error)
new JniInstanceMethods(typeof(JavaProxyThrowable))
This brings us to the
JniInstaceMethods(Type)
constructor: https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs#L17-L29Which calls
GetTypeSignature(typeof(JavaProxyThrowable))
: https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs#L51Which calls
GetUnderlyingType(typeof(JavaProxyThrowable), out int _)
: https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs#L140-L155Which is where things make no sense: statically, we know
type
istypeof(JavaProxyThrowable)
, yet here:https://github.com/xamarin/java.interop/blob/3fcce7466324c6564874fe275eac222a8970078c/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs#L151-L152
typeof(JavaProxyThrowable).IsEnum
must betrue
in order for us to hitEnum.GetUnderlyingType(typeof(JavaProxyThrowable))
, but it shouldn’t betrue
!Thus, throwing the
ArgumentException
is correct behavior.The bug is that
typeof(JavaProxyThrowable).IsEnum
istrue
when it should befalse
!(Or AOT+LLVM inlining mumble something?)
Let’s just close it, and I can reopen if we hit this again.
@lambdageek this particular issue, I haven’t seen last time I tested LLVM. Is it possible some change since May solved this one?
I’ve more recently hit these two:
@SamMonoRT this issue is only happening in .NET 7.
It looks like the same test is passing in .NET 6.