Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[monodroid] typemaps may need to load assemblies (#8625)
Context: dotnet/java-interop@005c914 Context: dotnet/java-interop#1181 Context: 25d1f00 When attempting to bump to dotnet/java-interop@005c9141, multiple unit tests would fail, e.g. Java.Lang.LinkageError : net.dot.jni.test.CallVirtualFromConstructorDerived ----> System.NotSupportedException : Could not find System.Type corresponding to Java type JniTypeSignature(TypeName=net/dot/jni/test/CallVirtualFromConstructorDerived ArrayRank=0 Keyword=False) . This happened because dotnet/java-interop@005c9141 implicitly required that typemaps exist for `Java.Interop.JavaObject` subclasses. Fair enough; enter xamasrin/java.interop#1181, which added support to `Java.Interop.Tools.JavaCallableWrappers` to emit typemaps for `Java.Interop.JavaObject` subclasses. That caused *crashes* in `tests/Mono.Android-Tests`: E droid.NET_Test: JNI ERROR (app bug): accessed stale Local 0x75 (index 7 in a table of size 7) F droid.NET_Test: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x75 … F droid.NET_Test: runtime.cc:630] native: #13 pc 00000000003ce865 /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::CheckJNI::GetObjectClass(_JNIEnv*, _jobject*)+837) The immediate cause of the crash was a "use after free" bug within `TypeManager.CreateInstance()` in a never-hit-before error path; the "use after free" bug was fixed in 25d1f00. However, the cause of the hitting a never-hit-before error path is because `EmbeddedAssemblies::typemap_java_to_managed()` would only map Java types to `System.Type` instances for assemblies that have *already been loaded*. If the assembly had not yet been loaded, then `EmbeddedAssemblies::typemap_java_to_managed()` would return `null`, and if the binding it couldn't find happens to be for `java.lang.Object`, we hit the (buggy!) "Where is the Java.Lang.Object wrapper" error condition. Commit 25d1f00 fixes that and a great many other related issues. What's left is `EmbeddedAssemblies::typemap_java_to_managed()`: it should *never* return null *unless* there is no typemap at all. Whether the target assembly has been loaded or not should be irrelevant. Update `EmbeddedAssemblies::typemap_java_to_managed()` so that it will load the target assembly if necessary. Additionally, before we figured out that we had a "use after free" bug, all we had to go on was that *something* related to `JNIEnv::GetObjectClass()` was involved. Review JNI usage around `JNIEnv::GetObjectClass()` and related invocations, and cleanup: * Simplify logic related to `JNIEnv::DeleteLocalRef()`. * Decrease scope of local variables. * Clear variables passed to `JNIEnv.DeleteLocalRef()`. Co-authored-by: Jonathan Pryor <[email protected]> Co-authored-by: Marek Habersack <[email protected]>
- Loading branch information