Skip to content

MonoVM + DynamicMethod semantic compatibility break between net7 & net8 #77273

@jonpryor

Description

@jonpryor

Description

Context: dotnet/android#7451
Context: e465230
Context: https://github.com/xamarin/xamarin-android/blob/91669a4e489104668fdd07382e40cf070aa559ac/src/Mono.Android.Export/CallbackCode.cs#L640-L641

When attempting to update xamarin/xamarin-android to use .NET 8, one of our unit tests started failing:

JNI DETECTED ERROR IN APPLICATION: JNI GetStringUTFChars called with pending exception android.runtime.JavaProxyThrowable: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. (TaskId:1071)
 ---> System.NotSupportedException: Wrong MethodAttributes or CallingConventions for DynamicMethod. Only public, static, standard supported (TaskId:1071)
   at System.Reflection.Emit.DynamicMethod.CheckConsistency(MethodAttributes attributes, CallingConventions callingConvention) (TaskId:1071)
   at System.Reflection.Emit.DynamicMethod.Init(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] signature, Type owner, Module m, Boolean skipVisibility, Boolean transparentMethod) (TaskId:1071)
   at System.Reflection.Emit.DynamicMethod..ctor(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, Boolean skipVisibility) (TaskId:1071)
   at Java.Interop.DynamicCallbackCodeGenerator.GenerateNativeCallbackDelegate() (TaskId:1071)
   at Java.Interop.DynamicCallbackCodeGenerator.GetCallback() (TaskId:1071)
   at Java.Interop.DynamicCallbackCodeGenerator.Create(MethodInfo method) (TaskId:1071)
   at System.Reflection.MethodInvoker.InterpretedInvoke(Object obj, Span`1 args, BindingFlags invokeAttr) (TaskId:1071)
   --- End of inner exception stack trace --- (TaskId:1071)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) (TaskId:1071)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) (TaskId:1071)
   at Android.Runtime.AndroidTypeManager.CreateDynamicCallback(MethodInfo method) (TaskId:1071)
   at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType nativeClass, Type type, ReadOnlySpan`1 methods) (TaskId:1071)
  at void mono.android.Runtime.register(java.lang.String, java.lang.Class, java.lang.String) (Runtime.java:-2) (TaskId:1071)
  at void crc641855b07eca6dcc03.ContainsExportedMethods.<clinit>() (ContainsExportedMethods.java:15) (TaskId:1071)
  at java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:-2) (TaskId:1071)
  at java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:454) (TaskId:1071)
  at void crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart() (TestInstrumentation_1.java:-2) (TaskId:1071)
  at void crc643df67da7b13bb6b1.TestInstrumentation_1.onStart() (TestInstrumentation_1.java:35) (TaskId:1071)
  at void android.app.Instrumentation$InstrumentationThread.run() (Instrumentation.java:2189) (TaskId:1071)

This test worked successfully under .NET 6 and .NET 7, failing only with an attempt to bump to 6367772.

We believe that commit e465230 broke our CallbackCode.GenerateNativeCallbackDelegate() method, as it only passes System.Reflection.MethodAttributes.Static, *not * MethodAttributes.Static | MethodAttributes.Public.

This code has been passing only MethodAttributes.Static to DynamicMethod since 2012.

Thus, the philosophical question: is this a regression that dotnet/runtime should fix? Or will this be considered a "valid breaking change" that needs to be fixed outside of dotnet/runtime?

Reproduction Steps

Current repro is part of a xamarin/xamarin-android unit test.

Expected behavior

No exception?

Actual behavior

NotSupportedException

Regression?

This is a regression compared to MonoVM + .NET 7.

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions