Description
Context: dotnet/android#9913
Context: dotnet/android@de49d96
dotnet/android#9913 updated JNIEnv.GetJniName(Type)
to use JniRuntime.JniTypeManager.GetTypeSignature(Type)
. It promptly failed on CI:
E NUnit : : System.NotSupportedException : 'Java.InteropTests.GenericHolder`1[T]' contains a generic type definition. This is not supported.
E NUnit : at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type )
E NUnit : at Android.Runtime.JNIEnv.GetJniName(Type )
E NUnit : at Java.Interop.TypeManager.RegisterType(String , Type )
E NUnit : at Android.Runtime.JNIEnvInit.RegisterJniNatives(IntPtr , Int32 , IntPtr , IntPtr , Int32 )
E NUnit : at Java.Interop.JniEnvironment.Object.AllocObject(JniObjectReference )
E NUnit : at Java.Interop.JniType.AllocObject()
E NUnit : at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
E NUnit : at Java.Lang.Object..ctor()
E NUnit : at Java.InteropTests.GenericHolder`1[[System.Int32, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor()
E NUnit : at Java.InteropTests.JnienvTest.NewClosedGenericTypeWorks()
E NUnit : at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
E NUnit : at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags )
because of this check:
java-interop/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Lines 148 to 149 in 19ec1a9
Should we have that check, first?
We certainly allow generic types to be Java.Lang.Object
subclasses, e.g. GenericHolder<T>
! Constructing instances of such types need to go through the type manager; should .GetTypeSignature()
really be asserting that generic type parameters not exist?
Or is it because we're using the type definition? typeof(GenericHolder<int>).ContainsGenericParameters
is false, i.e. that would pass the check; it's typeof(GenericHolder<>).ContainsGenericParameters
which fails.
Indeed, it's because between JniEnvironment.Object.AllocObject()
and JNIEnvInit.RegisterJniNatives()
is the static constructor for the Java Callable Wrapper for GenericHolder<T>
, which must implicitly use the type definition, as it cannot know what type parameters will be used:
public /* partial */ class GenericHolder_1
{
public static final String __md_methods;
static {
__md_methods = "";
mono.android.Runtime.register ("Java.InteropTests.GenericHolder`1, Mono.Android-Tests", GenericHolder_1.class, __md_methods);
}
}
Given that we later use a generic type definition:
java-interop/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs
Lines 160 to 170 in 19ec1a9
we can probably just remove the check entirely.