Repository navigation
Enable IsAotCompatible=true, to identify trimmer warnings in Java.Interop.dll #1157
Description
Activity
Related: dotnet/maui#5041
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.dlla@(TrimmerRootAssembly) - Publish and verify there are 0 trimmer warnings
This is more comprehensive than just setting
IsAotCompatible=true.- addedenhancementProposed change to current functionalityProposed change to current functionalityjava-interopRuntime bridge between .NET and JavaRuntime bridge between .NET and Java
on Nov 7, 2023 Results of running
<IsAotCompatible>onJava.Interoptoday: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.Reacted by Jonathan PeppersRan into many of these as part of PR #1153, which brings me to:
- https://github.com/xamarin/java.interop/blob/93a901a8207ded8b8ec124c64ad76d7a7a2d3779/samples/Hello-NativeAOTFromJNI/README.md#typegettype
- https://github.com/xamarin/java.interop/blob/93a901a8207ded8b8ec124c64ad76d7a7a2d3779/samples/Hello-NativeAOTFromJNI/README.md#type-maps
The
ManagedPeer.cswarnings are because it usesType.GetType()for a string value provided by Java, specifically from the Java Callable Wrappers. PR #1153 "makes this work" by adding aRegisterNativeMembers()overload which takes aReadOnlySpan<char>instead of aType-- overridden inNativeAotTypeManager-- and while allows registration to proceed, it doesn't fix theManagedPeer.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 onJniRuntime.JniTypeManager, allowing a subclass to provide its own mapping?The
Expressionscode is never used in .NET Android, and in a NativeAOT context if (when?) used will require the use ofjnimarshalmethod-genin 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*Invokertypes for interface wrapping.Part of me wonders if "fuller NativeAOT support" will require that
jcw-gen/etc. not only emit.javacode, 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 havejcw-genemit "something" in C#/IL which would allow mapping the "ctor sig" string tonew[]{typeof(int), typeof(string)}, which would allowType.GetConstructor()to work? Or we rethink how constructors work by having them invoke anativemethod, plus associated "magic" to make that work? (I can see that working withjnimarshalmethod-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 fromgeneratoroutput…)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.
@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#L14Issue #1165 has some thoughts on how to remove
Type.GetType()fromManagedPeer.cs. I'll need to think about the other issues separately.There are some reasonable docs in:
- https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/compiler-generated-code-handling.md
- https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/redundant-suppressions.md
[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).1 remaining item
An idea occurs to me around the IL2026 warnings around
System.Linq.Expressions.Expression.Property(): I should look into moving that code intoJava.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.Exportat 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-genruns, then this is a plausible way to "totally" fix the warnings, and even in a "current .NET Android world order" simply moving that code intoJava.Interop.Exportwill also remove those warnings…)- added a commit that references this issue
on Dec 2, 2023 - added 4 commits that reference this issue
on Feb 5, 2024 - added a commit that references this issue
on Feb 13, 2024 - added a commit that references this issue
on Feb 13, 2024 - added a commit that references this issue
on Feb 14, 2024 - moved this from Todo to Done in .NET 9 MAUI Performance, App Size, Inner Loop
on Feb 14, 2024 - added a commit that references this issue
on Feb 22, 2024 - locked and limited conversation to collaborators
on Apr 12, 2024 - added a commit that references this issue
on Jul 1, 2026
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
IsAotCompatiblein this repo, this implicitly sets:Then we'd want to address all the warnings and potentially make trimmer warnings build errors? FYI @jonpryor