-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Java.Interop] Typemap support for JavaObject &
[JniTypeSignature]
(#…
…1181) Context: dotnet/android#8543 Context: dotnet/android#8625 Context: dotnet/android#8681 Context: #1168 Context: def5bc0 Context: 005c914 dotnet/android#8543 tested PR #1168, was Totally Green™ -- finding no issues -- and so we merged PR #1168 into 005c914. Enter dotnet/android#8625, which bumps xamarin-android to use def5bc0, which includes 005c914. dotnet/android#8625 contains *failing unit tests* (?!), including `Java.InteropTests.InvokeVirtualFromConstructorTests()`: 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) . at Java.Interop.JniEnvironment.StaticMethods.GetStaticMethodID(JniObjectReference , String , String ) at Java.Interop.JniType.GetStaticMethod(String , String ) at Java.Interop.JniPeerMembers.JniStaticMethods.GetMethodInfo(String , String ) at Java.Interop.JniPeerMembers.JniStaticMethods.GetMethodInfo(String ) at Java.Interop.JniPeerMembers.JniStaticMethods.InvokeObjectMethod(String , JniArgumentValue* ) at Java.InteropTests.CallVirtualFromConstructorDerived.NewInstance(Int32 value) at Java.InteropTests.InvokeVirtualFromConstructorTests.ActivationConstructor() at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags ) --- End of managed Java.Lang.LinkageError stack trace --- java.lang.NoClassDefFoundError: net.dot.jni.test.CallVirtualFromConstructorDerived at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart(Native Method) at crc643df67da7b13bb6b1.TestInstrumentation_1.onStart(TestInstrumentation_1.java:35) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) Caused by: android.runtime.JavaProxyThrowable: [System.NotSupportedException]: Could not find System.Type corresponding to Java type JniTypeSignature(TypeName=net/dot/jni/test/CallVirtualFromConstructorDerived ArrayRank=0 Keyword=False) . at Java.Interop.ManagedPeer.GetTypeFromSignature(Unknown Source:0) at Java.Interop.ManagedPeer.RegisterNativeMembers(Unknown Source:0) at net.dot.jni.ManagedPeer.registerNativeMembers(Native Method) at net.dot.jni.test.CallVirtualFromConstructorDerived.<clinit>(CallVirtualFromConstructorDerived.java:12) ... 3 more --NotSupportedException at Java.Interop.ManagedPeer.GetTypeFromSignature(JniTypeManager , JniTypeSignature , String ) at Java.Interop.ManagedPeer.RegisterNativeMembers(IntPtr jnienv, IntPtr klass, IntPtr n_nativeClass, IntPtr n_methods) :shocked-pikachu-face: (But dotnet/android#8543 was green!) The problem is twofold: 1. 005c914 now requires the presence of typemap entries from e.g. `net.dot.jni.test.CallVirtualFromConstructorDerived` to `Java.InteropTests.CallVirtualFromConstructorDerived`. 2. `Java.Interop.Tools.JavaCallableWrappers` et al doesn't create typemap entries for `Java.Interop.JavaObject` subclasses which have `[JniTypeSignature]`. Consequently, our units tests fail (and apparently weren't *run* on dotnet/android#8543?! Still not sure what happened.) Update typemap generation by adding a new `TypeDefinition.HasJavaPeer()` extension method to replace all the `.IsSubclassOf("Java.Lang.Object")` and similar checks, extending it to also check for `Java.Interop.JavaObject` and `Java.Interop.JavaException` base types. (Continuing to use base type checks is done instead of just relying on implementation of `Java.Interop.IJavaPeerable` as a performance optimization, as there could be *lots* of interface types to check.) Additionally, @jonathanpeppers -- while trying to investigate all this -- ran across a build failure: obj\Debug\net9.0-android\android\src\java\lang\Object.java(7,15): javac.exe error JAVAC0000: error: cyclic inheritance involving Object This suggests that `Java.Interop.Tools.JavaCallableWrappers` was encountering `Java.Interop.JavaObject` -- or some other type which has `[JniTypeSignature("java/lang/Object")]` -- which is why `java/lang/Object.java` was being generated. Audit all `[JniTypeSignature]` attributes, and add `GenerateJavaPeer=false` to all types which should *not* hava a Java Callable Wrapper generated for them. This includes nearly everything within `Java.Interop-Tests.dll`. (We want the typemaps! We *don't* want generated Java source, as we have hand-written Java peer types for those tests.) Add `[JniTypeSignature]` to `GenericHolder<T>`. This type mapping isn't *actually* required, but it *is* used in `JavaVMFixture`, and it confuses people (me!) if things are inconsistent. Additionally, remove `tests/` from the Java-side name, for consistency. ~~ Avoid multiple java/lang/Object bindings ~~ A funny thing happened when in dotnet/android#8681 -- which tested this commit -- when using an intermediate version of this commit: unit tests started crashing! E monodroid-assembly: typemap: unable to load assembly 'Java.Interop-Tests' when looking up managed type corresponding to Java type 'java/lang/Object' What appears to be happening is an Unfortunate Interaction™: 1. `Java.Interop-Tests.dll` contained *multiple bindings* for `java/lang/Object`. e.g. [JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)] partial class JavaDisposedObject : JavaObject { } 2. The typemap generator has no functionality to "prioritize" one binding vs. another; it's random. As such, there is nothing to cause `Java.Lang.Object, Mono.Android` to be used as the preferred binding for `java/lang/Object`. This meant that when we hit the typemap codepath in .NET Android, we looked for the C# type that corresponded to `java/lang/Object`, found *some random type* from `Java.Interop-Tests`, and… …and then we hit another oddity: that codepath only supported looking for C# types in assemblies which had already been loaded. This was occurring during startup, so `Java.Interop-Tests` had not yet been loaded yet, so it errored out, returned `nullptr`, and later Android just aborts things: F droid.NET_Test: runtime.cc:638] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x79 Just…eep! This didn't happen before because `Java.Interop.JavaObject` subclasses *didn't* participate in typemap generation. This commit *adds* that support, introducing this unforeseen interaction. Fix this by *removing* most "alternate bindings" for `java/lang/Object`: - [JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)] + [JniTypeSignature (JniTypeName)] partial class JavaDisposedObject : JavaObject { + internal const string JniTypeName = "net/dot/jni/test/JavaDisposedObject"; } This implicitly requires that we now have a Java Callable Wrapper for this type, so update `Java.Interop-Tests.csproj` to run `jcw-gen` as part of the build process. This ensures that we create the JCW for e.g. `JavaDisposedObject`. Update `JavaVMFixture` to add the required typemap entries. --- Aside: this project includes [T4 Text Templates][0]. To regenerate the output files *without involving Visual Studio*, you can install the [`dotnet-t4`][1] tool: $ dotnet tool install --global dotnet-t4 then run it separately for each `.tt` file: $HOME/.dotnet/tools/t4 -o src/Java.Interop/Java.Interop/JavaPrimitiveArrays.cs \ src/Java.Interop/Java.Interop/JavaPrimitiveArrays.tt [0]: https://learn.microsoft.com/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2022 [1]: https://www.nuget.org/packages/dotnet-t4/
- Loading branch information
Showing
28 changed files
with
110 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.