Skip to content

Conversation

@grendello
Copy link
Contributor

Java typemaps have never included interfaces because, till very
recently, they couldn't contain methods so they couldn't have been used
as method invocation targets. With the addition of DIM (Default
Interface Methods) to C# this is no longer true. Exclusion of
interfaces from typemaps can lead to errors similar to:

---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.App.Application+IActivityLifecycleCallbacks)).JniTypeName="" != "android/app/Application$ActivityLifecycleCallbacks"
---- Assert Long Message ----
    at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005586+0x0
    at System.Diagnostics.Debug.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005548+0x0
    at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005545+0x0
    at System.Diagnostics.Debug.Assert(Boolean condition, String message) in System.Private.CoreLib.dll:token 0x6005544+0x0
    at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032e+0x0
    at Java.Interop.JniPe
Process terminated due to "ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.App.Application+IActivityLifecycleCallbacks)).JniTypeName="" != "android/app/Application$ActivityLifecycleCallbacks"
   at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005586+0x0
   at System.Diagnostics.Debug.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005548+0x0
   at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005545+0x0
   at System.Diagnostics.Debug.Assert(Boolean condition, String message) in System.Private.CoreLib.dll:token 0x6005544+0x0
   at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032e+0x0
   at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032c+0x0
   at Android.Runtime.XAPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean isInterface) in Mono.Android.dll:token 0x6017ed3+0x0
   at Android.App.Application.IActivityLifecycleCallbacks..cctor() in Mono.Android.dll:token 0x6025027+0x0
   at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType nativeClass, Type type, String methods) in Mono.Android.dll:token 0x6017c19+0x0
   at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr typeName_ptr, Int32 typeName_len, IntPtr jniClass, IntPtr methods_ptr, Int32 methods_len) in Mono.Android.dll:token 0x6017d48+0x0
   at Java.Interop.NativeMethods.java_interop_jnienv_alloc_object(IntPtr , IntPtr& , IntPtr ) in Java.Interop.dll:token 0x0+0x0
   at Java.Interop.JniEnvironment.Object.AllocObject(JniObjectReference type) in Java.Interop.dll:token 0x6000563+0x0
   at Java.Interop.JniType.AllocObject() in Java.Interop.dll:token 0x60003a1+0x0
   at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String constructorSignature, Type declaringType, JniArgumentValue* parameters) in Java.Interop.dll:token 0x60005e5+0x0
   at Java.Lang.Object..ctor() in Mono.Android.dll:token 0x601ea58+0x0
   at Microsoft.Maui.MauiApplication.ActivityLifecycleCallbacks..ctor() in Microsoft.Maui.dll:token 0x60004ef+0x0
   at Microsoft.Maui.MauiApplication`1[[HelloMaui.Startup, HelloMaui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnCreate() in Microsoft.Maui.dll:token 0x6000114+0x0
   at Android.App.Application.n_OnCreate(IntPtr jnienv, IntPtr native__this) in Mono.Android.dll:token 0x60153c7+0x0
   at Android.Runtime.DynamicMethodNameCounter.1(IntPtr , IntPtr ) in Mono.Android.dll:token 0x0+0x0"

This is caused by the fact that a class (MauiApplication.ActivityLifecycleCallbacks
in this case) implements a Java interace (IActivityLifecycleCallbacks
here) but it does not implement all the interface memebers. In such
instance, the default interface methods will be called (if available).

Xamarin.Android pairs each Java interface with a class, called an
Invoker, which is used for actual invocation of the interface methods.
In the case of the above crash, however, the
IActivityLifecycleCallbacksInvoker class doesn't implement one of the
IActivityLifecycleCallbacks interface methods (OnActivityPostCreated)
which causes Android.Runtime.AndroidTypeManager.RegisterNativeMembers
to attempt to invoke the default method in
IActivityLifecycleCallbacks. This, in turn, leads to XAPeerMembers
attempting to map its owner's managed type (IActivityLifecycleCallbacks)
to its Java counterpart by using a typemap lookup. However, since
interfaces aren't present in typemaps, the lookup fails and we get the
above exception.

Fix the issue by including all interfaces implementing the
Java.Interop.IJavaPeerable interface in typemaps.

Java typemaps have never included interfaces because, till very
recently, they couldn't contain methods so they couldn't have been used
as method invocation targets.  With the addition of DIM (Default
Interface Methods) to C# this is no longer true.  Exclusion of
interfaces from typemaps can lead to errors similar to:

    ---- DEBUG ASSERTION FAILED ----
    ---- Assert Short Message ----
    ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.App.Application+IActivityLifecycleCallbacks)).JniTypeName="" != "android/app/Application$ActivityLifecycleCallbacks"
    ---- Assert Long Message ----
        at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005586+0x0
        at System.Diagnostics.Debug.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005548+0x0
        at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005545+0x0
        at System.Diagnostics.Debug.Assert(Boolean condition, String message) in System.Private.CoreLib.dll:token 0x6005544+0x0
        at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032e+0x0
        at Java.Interop.JniPe
    Process terminated due to "ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.App.Application+IActivityLifecycleCallbacks)).JniTypeName="" != "android/app/Application$ActivityLifecycleCallbacks"
       at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005586+0x0
       at System.Diagnostics.Debug.Fail(String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005548+0x0
       at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage) in System.Private.CoreLib.dll:token 0x6005545+0x0
       at System.Diagnostics.Debug.Assert(Boolean condition, String message) in System.Private.CoreLib.dll:token 0x6005544+0x0
       at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032e+0x0
       at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean isInterface) in Java.Interop.dll:token 0x600032c+0x0
       at Android.Runtime.XAPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean isInterface) in Mono.Android.dll:token 0x6017ed3+0x0
       at Android.App.Application.IActivityLifecycleCallbacks..cctor() in Mono.Android.dll:token 0x6025027+0x0
       at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType nativeClass, Type type, String methods) in Mono.Android.dll:token 0x6017c19+0x0
       at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr typeName_ptr, Int32 typeName_len, IntPtr jniClass, IntPtr methods_ptr, Int32 methods_len) in Mono.Android.dll:token 0x6017d48+0x0
       at Java.Interop.NativeMethods.java_interop_jnienv_alloc_object(IntPtr , IntPtr& , IntPtr ) in Java.Interop.dll:token 0x0+0x0
       at Java.Interop.JniEnvironment.Object.AllocObject(JniObjectReference type) in Java.Interop.dll:token 0x6000563+0x0
       at Java.Interop.JniType.AllocObject() in Java.Interop.dll:token 0x60003a1+0x0
       at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String constructorSignature, Type declaringType, JniArgumentValue* parameters) in Java.Interop.dll:token 0x60005e5+0x0
       at Java.Lang.Object..ctor() in Mono.Android.dll:token 0x601ea58+0x0
       at Microsoft.Maui.MauiApplication.ActivityLifecycleCallbacks..ctor() in Microsoft.Maui.dll:token 0x60004ef+0x0
       at Microsoft.Maui.MauiApplication`1[[HelloMaui.Startup, HelloMaui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnCreate() in Microsoft.Maui.dll:token 0x6000114+0x0
       at Android.App.Application.n_OnCreate(IntPtr jnienv, IntPtr native__this) in Mono.Android.dll:token 0x60153c7+0x0
       at Android.Runtime.DynamicMethodNameCounter.1(IntPtr , IntPtr ) in Mono.Android.dll:token 0x0+0x0"

This is caused by the fact that a class (`MauiApplication.ActivityLifecycleCallbacks`
in this case) implements a Java interace (`IActivityLifecycleCallbacks`
here) but it does not implement all the interface memebers.  In such
instance, the default interface methods will be called (if available).

Xamarin.Android pairs each Java interface with a class, called an
Invoker, which is used for actual invocation of the interface methods.
In the case of the above crash, however, the
`IActivityLifecycleCallbacksInvoker` class doesn't implement one of the
`IActivityLifecycleCallbacks` interface methods (`OnActivityPostCreated`)
which causes `Android.Runtime.AndroidTypeManager.RegisterNativeMembers`
to attempt to invoke the default method in
`IActivityLifecycleCallbacks`.  This, in turn, leads to `XAPeerMembers`
attempting to map its owner's managed type (`IActivityLifecycleCallbacks`)
to its Java counterpart by using a typemap lookup.  However, since
interfaces aren't present in typemaps, the lookup fails and we get the
above exception.

Fix the issue by including all interfaces implementing the
`Java.Interop.IJavaPeerable` interface in typemaps.
@grendello grendello requested a review from jonpryor April 21, 2021 16:40
grendello added a commit to grendello/xamarin-android that referenced this pull request Apr 21, 2021
Context: dotnet/java-interop#824

With `Java.Interop` Java type scanner now including Java interfaces in
the returned set of types, we need to ignore interfaces when generating
JCWs.
@jonpryor jonpryor merged commit ebd7d76 into dotnet:main Apr 21, 2021
@grendello grendello deleted the interfaces-in-typemap branch April 21, 2021 20:35
grendello added a commit to grendello/xamarin-android that referenced this pull request Apr 21, 2021
Context: dotnet/java-interop#824

With `Java.Interop` Java type scanner now including Java interfaces in
the returned set of types, we need to ignore interfaces when generating
JCWs.
grendello added a commit to grendello/xamarin-android that referenced this pull request Apr 22, 2021
Context: dotnet/java-interop#824

With `Java.Interop` Java type scanner now including Java interfaces in
the returned set of types, we need to ignore interfaces when generating
JCWs.
@jpobst jpobst added this to the 11.3 (16.10 / 8.10) milestone May 5, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants