[Java.Interop] Generic Type Definitions are allowed #1336
Merged
+25
−5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Context: dotnet/android#9913
Context: dotnet/android@de49d96
Fixes: #1324
dotnet/android#9913 updated
JNIEnv.GetJniName(Type)
to useJniRuntime.JniTypeManager.GetTypeSignature(Type)
.It promptly failed on CI:
because of this check within
JniRuntime.JniTypeManager.GetTypeSignature()
:Why is
type.ContainsGenericParameters
true?type.ContainsGenericParameters
is true because XAJavaInterop1-style Java Callable Wrappers contain an Assembly Qualified Type Name, and if the underlying type is generic, then the assembly qualified type name mentions the type definition. Consider:results in this Java Callable Wrapper snippet:
Note
Java.InteropTests.GenericHolder`1, Mono.Android-Tests
:Type.GetType("Java.InteropTests.GenericHolder`1, Mono.Android-Tests")
results in a type definition, in whichtype.ContainsGenericParameters
is true.Is this a problem? No, it is not a problem in type registration, as this has worked in dotnet/android for many years at this point.
Is this a problem elsewhere? Yes:
Instances of
GenericHolder_1
cannot be created from Java, because Java doesn't know what type parameters to provide, because of type erasure.[JavaCallable]
methods on generic types also cannot work, as only one method can be registered, while semantically a generic method is N methods (per type).Update
JniRuntime.JniTypeManager.GetTypeSignature()
to no longer check fortype.ContainsGenericParameters
.Update
JniTypeManagerTests
to assert that constructing instances from Java results in an exception.A "funny" thing happened when adding that test: it didn't assert! There are two reasons for this. The first is that the Java Callable Wrapper for
Java.InteropTests.GenericHolder<T>
did not have a Java constructor! Without a constructor, it had the default constructor, which has no such verification check.The cause of the missing constructor is that
Java.Interop.Tools.JavaCallableWrappers
needs to know the JNI signature of the constructor to generate, and theJavaObject
default constructor didn't have[JniConstructorSignature]
.Update the
JavaObject
default constructor appropriately:This causes the Java Callable Wrapper for
GenericHolder<T>
to have the desired constructor which callsManagedPeer.construct()
, which in turn is a prerequisite for throwingNotSupportedException
.The second issue is that the
CannotCreateGenericHolderFromJava()
test must useJNIEnv::AllocObject()
+JNIEnv::CallNonvirtualVoidMethod()
to construct the instance, notJNIEnv::NewObject()
, because we special-caseJNIEnv::NewObject()
; see also commit 1c99956.