-
Notifications
You must be signed in to change notification settings - Fork 556
[Xamarin.Android.Build.Tasks] Java.Interop has typemaps #9768
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or 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
If you have a Debug build of .NET for Android, and you enable assembly logging: % adb shell setprop debug.mono.log default,assembly then `adb logcat` will contain messages such as: I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.ManagedPeer, Java.Interop' W monodroid: typemap: failed to map managed type to Java type: Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (Module ID W monodroid-assembly: typemap: called from W monodroid-assembly: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type type) W monodroid-assembly: at Android.Runtime.AndroidTypeManager.GetSimpleReference(Type type) W monodroid-assembly: at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type type) W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType) W monodroid-assembly: at Java.Interop.ManagedPeer..cctor() W monodroid-assembly: at Java.Interop.JniRuntime..ctor(CreationOptions options) W monodroid-assembly: at Android.Runtime.AndroidRuntime..ctor(IntPtr jnienv, IntPtr vm, IntPtr classLoader, IntPtr classLoader_loadClass, Boolean jniAddNativeMethodRegistrationAttributePresent) W monodroid-assembly: at Android.Runtime.JNIEnvInit.Initialize(JnienvInitializeArgs* args) … I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.JavaObject, Java.Interop' W monodroid: typemap: failed to map managed type to Java type: Java.Interop.JavaObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (Module ID: 90427bf1-700a-4676-b23a-fb68e2e2e9da; Type token: 33554439) W monodroid-assembly: typemap: called from W monodroid-assembly: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type type) W monodroid-assembly: at Android.Runtime.AndroidTypeManager.GetSimpleReference(Type type) W monodroid-assembly: at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type type) W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType) W monodroid-assembly: at Java.Interop.JavaObject..cctor() W monodroid-assembly: at Java.Interop.TypeManager.Activate(IntPtr jobject, ConstructorInfo cinfo, Object[] parms) W monodroid-assembly: at Java.Interop.TypeManager.n_Activate(IntPtr jnienv, IntPtr jclass, IntPtr typename_ptr, IntPtr signature_ptr, IntPtr jobject, IntPtr parameters_ptr) W monodroid-assembly: at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLLL_V(_JniMarshal_PPLLLL_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3) `ManagedPeer` and `JavaObject` are types within `Java.Interop.dll` which uses `JniPeerMembers`, and [Debug builds of `JniPeerMembers`][0] try to verify that the typemap entry is consistent: partial class JniPeerMembers { JniPeerMembers string jniPeerTypeName, Type managedPeerType, bool checkManagedPeerType, bool isInterface = false) { // … #if DEBUG var signatureFromType = JniEnvironment.Runtime.TypeManager.GetTypeSignature (managedPeerType); if (signatureFromType.SimpleReference != jniPeerTypeName) { Debug.WriteLine ("WARNING-Java.Interop: ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof({0})).JniTypeName=\"{1}\" != \"{2}\"", managedPeerType.FullName, signatureFromType.SimpleReference, jniPeerTypeName); Debug.WriteLine (new System.Diagnostics.StackTrace (true)); } #endif // DEBUG } } However, `Java.Interop.dll` is not considered to be a .NET for Android assembly, as it's built with e.g. `$(TargetFramework)=net9.0` and not `$(TargetFramework)=net9.0-android`. As such, it is skipped during typemap processing. Update `XAJavaTypeScanner.SpecialAssemblies` so that `Java.Interop.dll` is explicitly processed. This will ensure that there is a typemap entry for `ManagedPeer` and that the `JniPeerMembers` checks pass. This allows typemap entries for `JavaObject` and `ManagedPeer` to be created, removing the above warning messages. [0]: https://github.com/dotnet/java-interop/blob/6bc87e8b55bc00ae1423a5ae92cf5db573fc76ed/src/Java.Interop/Java.Interop/JniPeerMembers.cs#L45-L54
dellis1972
approved these changes
Feb 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
Odd this hasn't caused any problems before?
jonathanpeppers
approved these changes
Feb 7, 2025
jonpryor
added a commit
to dotnet/java-interop
that referenced
this pull request
Feb 10, 2025
Context: dotnet/android#9768 dotnet/android#9768 attempts to add types from `Java.Interop.dll` to the .NET for Android typemaps, in order to fix Debug warnings like: I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.ManagedPeer, Java.Interop' Unfortunately, this causes the assertion: AssertGetJniTypeInfoForType (typeof (JavaArray<JavaObject>), "[Ljava/lang/Object;", false, 1); within `Java.InteropTests.JniTypeManagerTests.GetTypeSignature_Type()` to fail: Expected string length 19 but was 33. Strings differ at index 0. Expected: "[Ljava/lang/Object;" But was: "crc64d5d92128469ae06d/JavaArray_1" -----------^ The immediate cause of the failure is that `JniRuntime.JniTypeManager.GetTypeSignature()` called `JniRuntime.JniTypeManager.GetSimpleReference()` *before* it tried to see if the type was `JavaArray<T>`. As `Java.Interop.dll` was now being processed for typemap purposes, and because `JavaArray<T>` did not have a `[JniTypeSignatureAttribute]`, the typemap got the default behavior of `crc64[hash…]`. The broader cause is that `GetSimpleReference()` should be the *fallback* implementation, used after all other attempts to get a JNI name have failed. Update `GetTypeSignature()` and `GetTypeSignatures()` so that `GetSimpleReference()` and/or `GetSimpleReferences()` are in fact treated as fallbacks. Additionally, update `AssertGetJniTypeInfoForType()` to assert that the value returned by `GetTypeSignature()` is the same as the value return3ed by` GetTypeSignatures().First()`. This was *commented* as being the case, but we should *verify* that as well. Finally, update `AssertGetJniTypeInfoForType()` so that when the assertion fails, the source `type` value is provided.
Does It Build™?
Context: dotnet/java-interop@baf43b0 Support for MD5 was removed in dotnet/java-interop@baf43b09. Attempting to use it now results in an XAGJS7015 error: …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: System.NotSupportedException: PackageNamingPolicy.LowercaseHash is no longer supported. [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.GetPackageName(TypeDefinition type, IMetadataResolver resolver) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 683 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.<>c__DisplayClass56_0.<ToJniName>b__2(TypeDefinition t) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 552 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName[T](T type, Func`2 decl, Func`2 name, Func`2 ns, Func`2 overrideName, Func`2 shouldUpdateName) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 720 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName(TypeDefinition type, ExportParameterKind exportKind, IMetadataResolver cache) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 548 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName(TypeDefinition type, IMetadataResolver resolver) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 527 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Java.Interop.Tools.TypeNameMappings.JavaNativeTypeManager.ToJniName(TypeDefinition type, TypeDefinitionCache cache) in /Users/builder/azdo/_work/3/s/xamarin-android/external/Java.Interop/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs:line 523 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.TypeMapGenerator.GetDebugEntry(TypeDefinition td, TypeDefinitionCache cache) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs:line 345 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.TypeMapGenerator.GenerateDebugNativeAssembly(Boolean skipJniAddNativeMethodRegistrationAttributeScan, String outputDirectory) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs:line 266 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.TypeMapGenerator.GenerateDebug(Boolean skipJniAddNativeMethodRegistrationAttributeScan, String outputDirectory, Boolean generateNativeAssembly) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs:line 179 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.TypeMapGenerator.Generate(Boolean debugBuild, Boolean skipJniAddNativeMethodRegistrationAttributeScan, String outputDirectory, Boolean generateNativeAssembly) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Utilities/TypeMapGenerator.cs:line 170 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.GenerateJavaStubs.WriteTypeMappings(NativeCodeGenState state) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs:line 466 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.GenerateJavaStubs.Run(Boolean useMarshalMethods) in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs:line 269 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Xamarin.Android.Tasks.GenerateJavaStubs.RunTask() in /Users/builder/azdo/_work/3/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs:line 112 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] …\Xamarin.Android.Common.targets(1504,3): error XAGJS7015: at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/builder/azdo/_work/3/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25 [D:\a\_work\1\a\TestRelease\02-10_20.56.48\temp\PackageNamingPolicyLowercaseMD5\UnnamedProject.csproj] The only reason this hasn't failed before is because `Mono.Android.dll` is special-cased, so the PackageNamingPolicy value is ignored… until we start processing `Java.Interop.dll`! Remove `LowercaseMD5` from `BuildTest.PackageNamingPolicy()` and move it into a new `PackageNamingPolicy_LowercaseMD5_IsObsolete()` test which asserts that the build fails.
New typemaps, new file sizes.
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
`PackageNamingPolicy_LowercaseMD5_IsObsolete()` was failing because `$(AndroidManifest)` was set. Bad copy & paste! Fix: JNI ERROR (app bug): accessed stale Local 0xd1 (index 13 in a table of size 13) within `FromNative()`.
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Context: 25d1f00 THE STORY SO FAR Remember 25d1f00? > With a partially heavy heart, we need to special-case typemap entries > by processing `Mono.Android.dll` *first*, so that it gets first dibs > at bindings for `java/lang/Object` and other types. > > … > > Note that the special-casing needs to happen in `NativeTypeMappingData` > because typemaps were formerly processed in *sorted module order*, in > which the sort order is based on the *byte representation* of the > module's MVID (a GUID). Additionally, *linking changes the MVID*, > which means module order is *effectively random*. Consequently, > trying to special case typemap ordering anywhere else is ineffective. The above is only true for *Release* builds. *Debug* builds don't go through `NativeTypeMappingData`, and have a different mechanism and format for typemap data. Update `XAJavaTypeScanner.GetJavaTypes()` to process `Mono.Android.dll` *before* any other assemblies, ensuring that `java/lang/Object` is typemap'd to `Java.Lang.Object, Mono.Android.dll`. Add a new `ObjectTest.java_lang_Object_Is_Java_Lang_Object()` unit test which explicitly verifies the mapping for `java/lang/Object`.
The test doesn't fail now! …because, due to "special-casing" so that Mono.Android.dll is processed first -- and probably the `[JniTypeSignature]` additions in java-interop? -- we don't trigger the exception codepath now. ¯\_(ツ)_/¯
Draft commit message: Bump to dotnet/java-interop/main@d62008d1 (#9768)
Changes: https://github.com/dotnet/java-interop/compare/57f7bc849f36ec7c3159cc7729c7276b8dcd3ca4...d62008d1ad7f469f801c7c00613f3a9fc94648a1
* dotnet/java-interop@d62008d1: [Java.Interop] GetSimpleReferences(): fallback for GetTypeSignatures() (dotnet/java-interop#1305)
Context: 25d1f007a7bd1ca3ce960315fabd04b9a687224e
If you have a Debug build of .NET for Android, and you enable
assembly logging:
% adb shell setprop debug.mono.log default,assembly
then `adb logcat` will contain messages such as:
I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.ManagedPeer, Java.Interop'
W monodroid: typemap: failed to map managed type to Java type: Java.Interop.ManagedPeer, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (Module ID
W monodroid-assembly: typemap: called from
W monodroid-assembly: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type type)
W monodroid-assembly: at Android.Runtime.AndroidTypeManager.GetSimpleReference(Type type)
W monodroid-assembly: at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type type)
W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface)
W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
W monodroid-assembly: at Java.Interop.ManagedPeer..cctor()
W monodroid-assembly: at Java.Interop.JniRuntime..ctor(CreationOptions options)
W monodroid-assembly: at Android.Runtime.AndroidRuntime..ctor(IntPtr jnienv, IntPtr vm, IntPtr classLoader, IntPtr classLoader_loadClass, Boolean jniAddNativeMethodRegistrationAttributePresent)
W monodroid-assembly: at Android.Runtime.JNIEnvInit.Initialize(JnienvInitializeArgs* args)
…
I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.JavaObject, Java.Interop'
W monodroid: typemap: failed to map managed type to Java type: Java.Interop.JavaObject, Java.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 (Module ID: 90427bf1-700a-4676-b23a-fb68e2e2e9da; Type token: 33554439)
W monodroid-assembly: typemap: called from
W monodroid-assembly: at Android.Runtime.JNIEnv.TypemapManagedToJava(Type type)
W monodroid-assembly: at Android.Runtime.AndroidTypeManager.GetSimpleReference(Type type)
W monodroid-assembly: at Java.Interop.JniRuntime.JniTypeManager.GetTypeSignature(Type type)
W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface)
W monodroid-assembly: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
W monodroid-assembly: at Java.Interop.JavaObject..cctor()
W monodroid-assembly: at Java.Interop.TypeManager.Activate(IntPtr jobject, ConstructorInfo cinfo, Object[] parms)
W monodroid-assembly: at Java.Interop.TypeManager.n_Activate(IntPtr jnienv, IntPtr jclass, IntPtr typename_ptr, IntPtr signature_ptr, IntPtr jobject, IntPtr parameters_ptr)
W monodroid-assembly: at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLLL_V(_JniMarshal_PPLLLL_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2, IntPtr p3)
`ManagedPeer` and `JavaObject` are types within `Java.Interop.dll`
which uses `JniPeerMembers`, and [Debug builds of `JniPeerMembers`][0]
try to verify that the typemap entry is consistent:
partial class JniPeerMembers {
JniPeerMembers string jniPeerTypeName, Type managedPeerType, bool checkManagedPeerType, bool isInterface = false)
{
// …
#if DEBUG
var signatureFromType = JniEnvironment.Runtime.TypeManager.GetTypeSignature (managedPeerType);
if (signatureFromType.SimpleReference != jniPeerTypeName) {
Debug.WriteLine ("WARNING-Java.Interop: ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof({0})).JniTypeName=\"{1}\" != \"{2}\"",
managedPeerType.FullName,
signatureFromType.SimpleReference,
jniPeerTypeName);
Debug.WriteLine (new System.Diagnostics.StackTrace (true));
}
#endif // DEBUG
}
}
However, `Java.Interop.dll` is not considered to be a .NET for Android
assembly, as it's built with e.g. `$(TargetFramework)=net9.0` and not
`$(TargetFramework)=net9.0-android`. As such, it is skipped during
typemap processing.
Update `XAJavaTypeScanner.SpecialAssemblies` so that `Java.Interop.dll`
is explicitly processed. This will ensure that there is a typemap
entry for `ManagedPeer` and that the `JniPeerMembers` checks pass.
This allows typemap entries for `JavaObject` and `ManagedPeer` to be
created, removing the above warning messages.
This also requires updating `XAJavaTypeScanner.GetJavaTypes()` so
that in Debug builds, `Mono.Android.dll` is processed *before* any
other assemblies, ensuring that `java/lang/Object` is typemap'd to
`Java.Lang.Object, Mono.Android.dll`. See also 25d1f007, which did
the same thing for *Release* builds.
Add a new `ObjectTest.java_lang_Object_Is_Java_Lang_Object()` unit
test which explicitly verifies the mapping for `java/lang/Object`.
[0]: https://github.com/dotnet/java-interop/blob/6bc87e8b55bc00ae1423a5ae92cf5db573fc76ed/src/Java.Interop/Java.Interop/JniPeerMembers.cs#L45-L54 |
jonpryor
added a commit
to dotnet/java-interop
that referenced
this pull request
Feb 12, 2025
#1305) Context: dotnet/android#9768 dotnet/android#9768 attempts to add types from `Java.Interop.dll` to the .NET for Android typemaps, in order to fix Debug warnings like: I monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Java.Interop.ManagedPeer, Java.Interop' Unfortunately, the initial attempt to generate typemaps for `Java.Interop.dll` caused the assertion: AssertGetJniTypeInfoForType (typeof (JavaArray<JavaObject>), "[Ljava/lang/Object;", false, 1); within `Java.InteropTests.JniTypeManagerTests.GetTypeSignature_Type()` to fail with: Expected string length 19 but was 33. Strings differ at index 0. Expected: "[Ljava/lang/Object;" But was: "crc64d5d92128469ae06d/JavaArray_1" -----------^ The immediate cause of the failure is that `JniRuntime.JniTypeManager.GetTypeSignature()` called `JniRuntime.JniTypeManager.GetSimpleReference()` *before* it tried to see if the type was `JavaArray<T>`. As `Java.Interop.dll` was now being processed for typemap purposes, and because `JavaArray<T>` did not have a `[JniTypeSignatureAttribute]`, the typemap got the default behavior of `crc64[hash…]`. The broader cause is that `GetSimpleReference()` should be the *fallback* implementation, used after all other attempts to get a JNI name have failed. Update `GetTypeSignature()` and `GetTypeSignatures()` so that `GetSimpleReference()` and/or `GetSimpleReferences()` are in fact treated as fallbacks. Additionally, update `AssertGetJniTypeInfoForType()` to assert that the value returned by `GetTypeSignature()` is the same as the value return3ed by` GetTypeSignatures().First()`. This was *commented* as being the case, but we should *verify* that as well. Finally, *move* the `type.GetCustomAttribute<JniTypeSignatureAttribute()` and `GetReplacementType()` logic into `GetSimpleReferences()`. This This emphasizes the "fallback" nature of `GetSimpleReference()`, adds an missing `GetReplacementType()` invocation from the `GetTypeSignatures()` codepath, and this is what [`AndroidTypeManager.GetSimpleReference()`][0] was already doing. [0]: https://github.com/dotnet/android/blob/21c413195e300b6440eb437dade4f3a114e795f7/src/Mono.Android/Android.Runtime/AndroidRuntime.cs#L279-L289
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
dellis1972
approved these changes
Feb 12, 2025
Fully green here: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=10997525&view=results Not sure how two separate PR builds were started for this… |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
If you have a Debug build of .NET for Android, and you enable assembly logging:
then
adb logcat
will contain messages such as:ManagedPeer
andJavaObject
are types withinJava.Interop.dll
which usesJniPeerMembers
, and Debug builds ofJniPeerMembers
try to verify that the typemap entry is consistent:However,
Java.Interop.dll
is not considered to be a .NET for Android assembly, as it's built with e.g.$(TargetFramework)=net9.0
and not$(TargetFramework)=net9.0-android
. As such, it is skipped during typemap processing.Update
XAJavaTypeScanner.SpecialAssemblies
so thatJava.Interop.dll
is explicitly processed. This will ensure that there is a typemap entry forManagedPeer
and that theJniPeerMembers
checks pass. This allows typemap entries forJavaObject
andManagedPeer
to be created, removing the above warning messages.