Summary
InvokeVirtualFromConstructorTests (3 tests) fail on NativeAOT with DelegateMarshalling_MissingInteropData because PreserveRegistrations.cs does not handle [JniAddNativeMethodRegistrationAttribute].
Failing tests
InvokeVirtualFromConstructorTests.CreateJavaInstanceFirst
InvokeVirtualFromConstructorTests.CreateManagedInstanceFirst_WithAllocObject
InvokeVirtualFromConstructorTests.CreateManagedInstanceFirst_WithNewObject
Root cause
PreserveRegistrations.cs only processes methods with [Register] attributes (via TryGetRegisterMember). It has no awareness of [JniAddNativeMethodRegistrationAttribute], which is used by CallVirtualFromConstructorDerived.RegisterNativeMembers to register a CalledFromConstructorMarshalMethod delegate as a JNI native callback.
On NativeAOT, delegate types used as unmanaged function pointers need their interop stubs generated at compile time. Because PreserveRegistrations never tells the AOT compiler about CalledFromConstructorMarshalMethod, the runtime throws NotSupportedException: DelegateMarshalling_MissingInteropData when JniEnvironment.Types.RegisterNatives tries to convert the delegate to a function pointer.
Call path
ManagedTypeManager.RegisterNativeMembers calls base.RegisterNativeMembers (for empty methods string)
- Base class
FindAndCallRegisterMethod uses reflection to find [JniAddNativeMethodRegistrationAttribute] methods
CallVirtualFromConstructorDerived.RegisterNativeMembers(args) creates a CalledFromConstructorMarshalMethod delegate
- Delegate passed to
JniEnvironment.Types.RegisterNatives which needs unmanaged function pointer conversion
- NativeAOT has no interop stub ->
DelegateMarshalling_MissingInteropData
Proposed fix
Extend PreserveRegistrations (or add a companion ILLink step) to:
- Find methods marked with
[JniAddNativeMethodRegistrationAttribute]
- Analyze delegate types constructed within those methods
- Ensure those delegate types get their interop metadata preserved for NativeAOT
This would also affect any user code that uses [JniAddNativeMethodRegistrationAttribute] with NativeAOT.
Workaround
Tests are temporarily marked with [Category("NativeAOTIgnore")] in dotnet/java-interop.
Context: #10496
Summary
InvokeVirtualFromConstructorTests(3 tests) fail on NativeAOT withDelegateMarshalling_MissingInteropDatabecausePreserveRegistrations.csdoes not handle[JniAddNativeMethodRegistrationAttribute].Failing tests
InvokeVirtualFromConstructorTests.CreateJavaInstanceFirstInvokeVirtualFromConstructorTests.CreateManagedInstanceFirst_WithAllocObjectInvokeVirtualFromConstructorTests.CreateManagedInstanceFirst_WithNewObjectRoot cause
PreserveRegistrations.csonly processes methods with[Register]attributes (viaTryGetRegisterMember). It has no awareness of[JniAddNativeMethodRegistrationAttribute], which is used byCallVirtualFromConstructorDerived.RegisterNativeMembersto register aCalledFromConstructorMarshalMethoddelegate as a JNI native callback.On NativeAOT, delegate types used as unmanaged function pointers need their interop stubs generated at compile time. Because
PreserveRegistrationsnever tells the AOT compiler aboutCalledFromConstructorMarshalMethod, the runtime throwsNotSupportedException: DelegateMarshalling_MissingInteropDatawhenJniEnvironment.Types.RegisterNativestries to convert the delegate to a function pointer.Call path
ManagedTypeManager.RegisterNativeMemberscallsbase.RegisterNativeMembers(for empty methods string)FindAndCallRegisterMethoduses reflection to find[JniAddNativeMethodRegistrationAttribute]methodsCallVirtualFromConstructorDerived.RegisterNativeMembers(args)creates aCalledFromConstructorMarshalMethoddelegateJniEnvironment.Types.RegisterNativeswhich needs unmanaged function pointer conversionDelegateMarshalling_MissingInteropDataProposed fix
Extend
PreserveRegistrations(or add a companion ILLink step) to:[JniAddNativeMethodRegistrationAttribute]This would also affect any user code that uses
[JniAddNativeMethodRegistrationAttribute]with NativeAOT.Workaround
Tests are temporarily marked with
[Category("NativeAOTIgnore")]in dotnet/java-interop.Context: #10496