Skip to content

[NativeAOT] PreserveRegistrations does not handle [JniAddNativeMethodRegistrationAttribute] delegate types #10950

@jonathanpeppers

Description

@jonathanpeppers

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

  1. ManagedTypeManager.RegisterNativeMembers calls base.RegisterNativeMembers (for empty methods string)
  2. Base class FindAndCallRegisterMethod uses reflection to find [JniAddNativeMethodRegistrationAttribute] methods
  3. CallVirtualFromConstructorDerived.RegisterNativeMembers(args) creates a CalledFromConstructorMarshalMethod delegate
  4. Delegate passed to JniEnvironment.Types.RegisterNatives which needs unmanaged function pointer conversion
  5. NativeAOT has no interop stub -> DelegateMarshalling_MissingInteropData

Proposed fix

Extend PreserveRegistrations (or add a companion ILLink step) to:

  1. Find methods marked with [JniAddNativeMethodRegistrationAttribute]
  2. Analyze delegate types constructed within those methods
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: NativeAOTIssues that only occur when using NativeAOT.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions