You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Java.Interop] Avoid Type.GetType() in ManagedPeer
Fixes: #1165
Context: #1153
Context: #1157
When building for NativeAOT (#1153) or when building .NET Android
apps with `-p:IsAotcompatible=true` (#1157), we get [IL2057][0]
warnings from `ManagedPeer.cs`:
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.
These warnings are because `ManagedPeer.Construct()` and
`ManagedPeer.RegisterNativeMembers()` use `Type.GetType()` on string
values provided *from Java code*, and thus the IL trimmer does not
have visibility into those strings, and thus cannot reliably
determine which types need to be preserved:
// Java Callable Wrapper
/* partial */ class ManagedType
{
public static final String __md_methods;
static {
__md_methods =
"n_GetString:()Ljava/lang/String;:__export__\n" +
"";
net.dot.jni.ManagedPeer.registerNativeMembers (
/* nativeClass */ ManagedType.class,
/* assemblyQualifiedName */ "Example.ManagedType, Hello-NativeAOTFromJNI",
/* methods */ __md_methods);
}
public ManagedType (int p0)
{
super ();
if (getClass () == ManagedType.class) {
net.dot.jni.ManagedPeer.construct (
/* self */ this,
/* assemblyQualifiedName */ "Example.ManagedType, Hello-NativeAOTFromJNI",
/* constructorSignature */ "System.Int32, System.Runtime",
/* arguments */ new java.lang.Object[] { p0 });
}
}
}
`ManagedPeer.construct()` passes *two* sets of assembly-qualified
type names: `assemblyQualifiedName` contains the type to construct,
while `constructorSignature` contains a `:`-separated list of
assembly-qualified type names for the constructor parameters.
Each of these are passed to `Type.GetType()`.
`ManagedPeer.registerNativeMembers()` passes an assembly-qualified
type name to `ManagedPeer.RegisterNativeMembers()`, which passes the
assembly-qualified type name to `Type.GetType()` to find the type
to register native methods for.
If we more strongly rely on JNI signatures, we can remove the need
for Java Callable Wrappers to contain assembly-qualified type names
entirely, thus removing the need for `ManagedPeer` to use
`Type.GetType()`, removing the IL2057 warnings.
For `ManagedPeer.construct()`, `assemblyQualifiedName` can be
replaced with getting the JNI type signature from `self.getClass()`,
and `constructorSignature` can be replaced with a
*JNI method signature* of the calling constructor.
For `ManagedPeer.registerNativeMembers()`, `assemblyQualifiedName`
can be replaced with getting the JNI type signature from `nativeClass`.
// Java Callable Wrapper
/* partial */ class ManagedType
{
public static final String __md_methods;
static {
__md_methods =
"n_GetString:()Ljava/lang/String;:__export__\n" +
"";
net.dot.jni.ManagedPeer.registerNativeMembers (
/* nativeClass */ ManagedType.class,
/* methods */ __md_methods);
}
public ManagedType (int p0)
{
super ();
if (getClass () == ManagedType.class) {
net.dot.jni.ManagedPeer.construct (
/* self */ this,
/* constructorSignature */ "(I)V",
/* arguments */ new java.lang.Object[] { p0 });
}
}
}
Furthermore, if we add `[DynamicallyAccessedMembers]` to
`JniRuntime.JniTypeManager.GetType()`, we can fix some [IL2075][1]
warnings which appeared after fixing the IL2057 warnings.
Aside: Excising assembly-qualified type names from Java Callable
Wrappers had some "interesting" knock-on effects in the unit tests,
requiring that more typemap information be explicitly provided.
(This same information was *implicitly* provided before, via the
provision of assembly-qualified type names everywhere…)
[0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-warnings/IL2057
[1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-warnings/il2075
Copy file name to clipboardExpand all lines: src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs
// Init outside of `lock` in case we have recursive access:
82
+
// System.ArgumentException: An item with the same key has already been added. Key: Java.Interop.JavaProxyThrowable
83
+
// at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
84
+
// at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
85
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type declaringType) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 80
86
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type declaringType) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 80
87
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String constructorSignature, Type declaringType, JniArgumentValue* parameters) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 146
88
+
// at Java.Interop.JavaException..ctor(String message) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JavaException.cs:line 52
89
+
// at Java.Interop.JavaProxyThrowable..ctor(Exception exception) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JavaProxyThrowable.cs:line 15
90
+
// at Java.Interop.JniEnvironment.Exceptions.Throw(Exception e) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniEnvironment.Errors.cs:line 39
91
+
// at Java.Interop.JniRuntime.RaisePendingException(Exception pendingException) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniRuntime.cs:line 444
92
+
// at Java.Interop.JniTransition.Dispose() in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniTransition.cs:line 39
93
+
// at Java.Interop.ManagedPeer.RegisterNativeMembers(IntPtr jnienv, IntPtr klass, IntPtr n_nativeClass, IntPtr n_methods) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/ManagedPeer.cs:line 195
94
+
// at Java.Interop.NativeMethods.java_interop_jnienv_find_class(IntPtr jnienv, IntPtr& thrown, String classname)
95
+
// at Java.Interop.NativeMethods.java_interop_jnienv_find_class(IntPtr jnienv, IntPtr& thrown, String classname)
96
+
// at Java.Interop.JniEnvironment.Types.TryRawFindClass(IntPtr env, String classname, IntPtr& klass, IntPtr& thrown) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs:line 135
97
+
// at Java.Interop.JniEnvironment.Types.TryFindClass(String classname, Boolean throwOnError) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs:line 49
98
+
// at Java.Interop.JniEnvironment.Types.FindClass(String classname) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs:line 37
99
+
// at Java.Interop.JniType..ctor(String classname) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniType.cs:line 51
100
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type declaringType) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 27
101
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type declaringType) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 77
102
+
// at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String constructorSignature, Type declaringType, JniArgumentValue* parameters) in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs:line 146
103
+
// at Java.Lang.Object..ctor() in /Users/jon/Developer/src/xamarin/java.interop/src/Java.Base/obj/Debug-net7.0/mcw/Java.Lang.Object.cs:line 32
104
+
// at Java.BaseTests.MyIntConsumer..ctor(Action`1 action) in /Users/jon/Developer/src/xamarin/java.interop/tests/Java.Base-Tests/Java.Base/JavaToManagedTests.cs:line 77
105
+
// at Java.BaseTests.JavaToManagedTests.InterfaceInvokerMethod() in /Users/jon/Developer/src/xamarin/java.interop/tests/Java.Base-Tests/Java.Base/JavaToManagedTests.cs:line 26
0 commit comments