Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

Enable IsAotCompatible=true, to identify trimmer warnings in Java.Interop.dll #1157

Description

@jonathanpeppers

As one of the prerequisites for supporting NativeAOT, we should solve all the trim warnings in this repo.

For details, see:

As an initial step, we could try enabling IsAotCompatible in this repo, this implicitly sets:

  • IsTrimmable
  • EnableTrimAnalyzer
  • EnableAotAnalyzer
  • EnableSingleFileAnalyzer

Then we'd want to address all the warnings and potentially make trimmer warnings build errors? FYI @jonpryor

Activity

  1. added this to the 9.0.0 Planning milestone on Nov 7, 2023
  2. jonathanpeppers commented on Nov 7, 2023

    @jonathanpeppers
    MemberAuthor
  3. jonathanpeppers commented on Nov 7, 2023

    @jonathanpeppers
    MemberAuthor

    Ok, one other comment, is you can further test trimming by doing something like:

    • dotnet new console
    • Add project reference to Java.Interop.dll
    • Make Java.Interop.dll a @(TrimmerRootAssembly)
    • Publish and verify there are 0 trimmer warnings

    This is more comprehensive than just setting IsAotCompatible=true.

  4. added
    enhancementProposed change to current functionality
    java-interopRuntime bridge between .NET and Java
    on Nov 7, 2023
  5. jpobst commented on Nov 7, 2023

    @jpobst
    Contributor

    Results of running <IsAotCompatible> on Java.Interop today:

    ManagedPeer.cs(93,19,93,112): warning IL2057: Unrecognized value passed to the parameter 'typeName' of method 'System.Type.GetType(String, Boolean)'. It's not possible to guarantee the availability of the target type.
    ManagedPeer.cs(156,18,156,65): warning IL2057: Unrecognized value passed to the parameter 'typeName' of method 'System.Type.GetType(String, Boolean)'. It's not possible to guarantee the availability of the target type.
    ManagedPeer.cs(198,35,198,92): warning IL2057: Unrecognized value passed to the parameter 'typeName' of method 'System.Type.GetType(String, Boolean)'. It's not possible to guarantee the availability of the target type.
    JniValueMarshaler.cs(169,66,169,107): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniValueMarshaler.cs(200,7,202,17): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniValueMarshaler.cs(201,8,201,53): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniRuntime.JniMarshalMemberBuilder.cs(57,40,57,68): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'System.Reflection.Assembly.GetType(String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.cs(249,29,249,81): warning IL3050: Using member 'System.Runtime.InteropServices.Marshal.PtrToStructure(nint, Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Marshalling code for the object might not be available.
    JniRuntime.JniValueManager.cs(672,58,672,91): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniStringValueMarshaler.cs(44,60,44,95): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniRuntime.JniValueManager.cs(685,41,685,136): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniRuntime.JniValueManager.cs(703,7,707,20): warning IL2026: Using member 'System.Linq.Expressions.Expression.Call(Expression, String, Type[], params Expression[])' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniRuntime.JniValueManager.cs(704,32,704,85): warning IL2026: Using member 'System.Linq.Expressions.Expression.Property(Expression, String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Creating Expressions requires unreferenced code because the members being referenced by the Expression may be trimmed.
    JniRuntime.JniTypeManager.cs(300,22,300,79): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.
    JniRuntime.JniTypeManager.cs(304,22,304,76): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.
    JniRuntime.JniTypeManager.cs(313,22,313,48): warning IL3050: Using member 'System.Type.MakeArrayType()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The code for an array of the specified type might not be available.
    JniRuntime.JniMarshalMemberBuilder.cs(164,33,164,78): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'Java.Interop.JniValueMarshalerAttribute.MarshalerType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniValueManager.cs(363,12,363,56): warning IL3050: Using member 'System.Type.MakeGenericType(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.
    JniRuntime.JniValueManager.cs(354,13,354,50): warning IL2026: Using member 'System.Reflection.Assembly.GetType(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed.
    JniRuntime.JniValueManager.cs(359,30,360,91): warning IL2026: Using member 'System.Reflection.Assembly.GetType(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed.
    JniRuntime.JniValueManager.cs(363,12,363,56): warning IL2055: Call to 'System.Type.MakeGenericType(params Type[])' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type.
    JniRuntime.JniValueManager.cs(341,23,341,114): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in call to 'System.Type.GetConstructors(BindingFlags)'. The parameter 'type' of method 'Java.Interop.JniRuntime.JniValueManager.GetActivationConstructor(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniTypeManager.cs(414,28,414,96): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.NonPublicNestedTypes' in call to 'System.Type.GetNestedType(String, BindingFlags)'. The parameter 'type' of method 'Java.Interop.JniRuntime.JniTypeManager.TryLoadJniMarshalMethods(JniType, Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniTypeManager.cs(418,26,418,108): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod(Type, String, Type[])'. The return value of method 'System.Type.GetNestedType(String, BindingFlags)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniTypeManager.cs(464,32,464,64): warning IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods' in call to 'System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethods(Type)'. The parameter 'marshalType' of method 'Java.Interop.JniRuntime.JniTypeManager.FindAndCallRegisterMethod(Type, JniNativeMethodRegistrationArguments)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniValueManager.cs(596,29,597,38): warning IL3050: Using member 'System.Reflection.MethodInfo.MakeGenericMethod(params Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.
    JniRuntime.JniValueManager.cs(596,29,597,38): warning IL2060: Call to 'System.Reflection.MethodInfo.MakeGenericMethod(params Type[])' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method.
    JniRuntime.JniValueManager.cs(542,33,542,87): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'Java.Interop.JniValueMarshalerAttribute.MarshalerType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniValueManager.cs(557,21,557,42): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'type' of method 'Java.Interop.JniRuntime.JniValueManager.GetValueMarshaler(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniValueManager.cs(578,27,578,48): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'type' of method 'Java.Interop.JniRuntime.JniValueManager.GetValueMarshaler(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    JniRuntime.JniValueManager.cs(588,33,588,88): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'Java.Interop.JniValueMarshalerAttribute.MarshalerType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    
  6. jonpryor commented on Nov 8, 2023

    @jonpryor
    Contributor

    Ran into many of these as part of PR #1153, which brings me to:

    The ManagedPeer.cs warnings are because it uses Type.GetType() for a string value provided by Java, specifically from the Java Callable Wrappers. PR #1153 "makes this work" by adding a RegisterNativeMembers() overload which takes a ReadOnlySpan<char> instead of a Type -- overridden in NativeAotTypeManager -- and while allows registration to proceed, it doesn't fix the ManagedPeer.Construct() side of things, which means. you can't (currently) have Java Callable Wrapper constructors which take arguments.

    I do wonder if the 'glib one-off' comment is actually the most viable solution:

    Possible "quick hack": replace Type.GetType() use with calls to something on JniRuntime.JniTypeManager, allowing a subclass to provide its own mapping?

    The Expressions code is never used in .NET Android, and in a NativeAOT context if (when?) used will require the use of jnimarshalmethod-gen in order to AOT the Expressions, so this is mostly a manner of adding the appropriate custom attributes to silence the linker.

    Marshal.PtrToStructure() & related code should probably just migrate to using C#9 function pointers et al.

    Assembly.GetType() is in the "required" camp -- not for .NET Android per-se, but just in general -- as it and equivalent code in xamarin-android is used to look up *Invoker types for interface wrapping.

  7. jonpryor commented on Nov 8, 2023

    @jonpryor
    Contributor

    Part of me wonders if "fuller NativeAOT support" will require that jcw-gen/etc. not only emit .java code, but also emit C# code or IL for use by NativeAOT compilation. For example, given:

    class Example : Java.Lang.Object {
        [Export(SuperArgumentString="")]
        public Example(int a, String b) {}
    }

    the Java Callable Wrapper will currently use strings to allow looking up the constructor:

    ManagedPeer.construct (
        /* self */      this,
        /* aqn */       "Namespace.Example, Assembly",
        /* ctor sig */  "System.Int32, System.Runtime:System.String, System.Runtime",
        /* arguments */ new java.lang.Object[] { p0, p1 }
    );

    As we can't use Type.GetType() on the "ctor sig" argument value components within NativeAOT, maybe the "workaround" is to have jcw-gen emit "something" in C#/IL which would allow mapping the "ctor sig" string to new[]{typeof(int), typeof(string)}, which would allow Type.GetConstructor() to work? Or we rethink how constructors work by having them invoke a native method, plus associated "magic" to make that work? (I can see that working with jnimarshalmethod-gen, as it's updating the assembly anyway, so it could certainly just add more methods to register, but I'm less certain how to make this work in a .NET Android context where marshal methods come from generator output…)

  8. jonathanpeppers commented on Nov 8, 2023

    @jonathanpeppers
    MemberAuthor

    The Expressions code is never used in .NET Android, and in a NativeAOT context

    So, some of these warnings can go away by adding additional attributes that pass warning along to the caller. If xamarin-android never calls some of these, we're good.

    That might get us by to at least address the warnings here and be able to move on to xamarin-android.

  9. jonpryor commented on Nov 17, 2023

    @jonpryor
    Contributor

    @jonathanpeppers: are there any HOWTOs on how to "fix" or otherwise silence these warnings? Use [SuppressMessage]?

    I guess maybe [UnconditionalSuppressMessage]? https://github.com/dotnet/dotNext/blob/4c7d7f4ae3bbdcc5ef63ecfdb8b937d2032d1eea/src/DotNext/Text/Json/OptionalConverter.cs#L14

  10. jonpryor commented on Nov 17, 2023

    @jonpryor
    Contributor

    Issue #1165 has some thoughts on how to remove Type.GetType() from ManagedPeer.cs. I'll need to think about the other issues separately.

  11. jonathanpeppers commented on Nov 17, 2023

    @jonathanpeppers
    MemberAuthor

    There are some reasonable docs in:

    [UnconditionalSuppressMessage] should be the last resort, so if the problem is related to [RequiresUnreferencedCode] sometimes you just decorate the method to forward the warning to any callers (until you get to a caller you can't).

  12. 1 remaining item

  13. jonpryor commented on Nov 29, 2023

    @jonpryor
    Contributor

    An idea occurs to me around the IL2026 warnings around System.Linq.Expressions.Expression.Property(): I should look into moving that code into Java.Interop.Export.dll, and see what breaks (and if it can be fixed without breaking API).

    With Research Project jnimarshalmethod-gen™, the NativeAOT sample should (lol) be able to use expression tree output in the post-build step, removing the need for further expression tree usage, such that the final output doesn't need Java.Interop.Export at all. (I hope.)

    (Whether that would actually impact the linker warnings in a NativeAOT app/#1168 is a different question entirely; what target produces them? If it's after build and after jnimarshalmethod-gen runs, then this is a plausible way to "totally" fix the warnings, and even in a "current .NET Android world order" simply moving that code into Java.Interop.Export will also remove those warnings…)

  14. locked and limited conversation to collaborators on Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementProposed change to current functionalityjava-interopRuntime bridge between .NET and Java

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions