You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[monodroid] Handle managed -> Java duplicate type mapping correctly (#5459)
Fixes: #5409
Context: a017561
Context: bb55bb0
Yet Another Java :: Managed Type Aliasing Issue.
Type aliasing occurs when multiple managed types bind the same Java
type. One common scenario for this is for `abstract` classes:
// Java:
public abstract class LayoutInflater {
// …
}
// C# Binding
[Register ("android/view/LayoutInflater", DoNotGenerateAcw=true)]
public abstract class LayoutInflater : Java.Lang.Object {
static readonly JniPeerMembers _members = new XAPeerMembers ("android/view/LayoutInflater", typeof (LayoutInflater));
}
// Used at runtime
[Register ("android/view/LayoutInflater", DoNotGenerateAcw=true)]
internal partial class LayoutInflaterInvoker : LayoutInflater {
static readonly JniPeerMembers _members = new XAPeerMembers ("android/view/LayoutInflater", typeof (LayoutInflaterInvoker));
}
Both the C# `LayoutInflater` and `LayoutInflaterInvoker` types *alias*
the Java `LayoutInflater` type.
In a *Debug* configuration build, the mappings between the Java types
and Managed types is held within a per-assembly mapping (7117414),
and because of a017561 there is no explicit managed entry for
`LayoutInflaterInvoker`:
DebugTypemap = {
.java_to_managed = {
{ "android/view/LayoutInflater", 0 }, // Java LayoutInflater -> C# LayoutInflater
{ "android/view/LayoutInflater", 0 }, // Java LayoutInflater -> C# LayoutInflater
},
.managed_to_java = {
{ "Android.Views.LayoutInflater", 0 }, // C# LayoutInflater -> Java LayoutInflater
{ "Android.Views.LayoutInflater", 0 }, // C# LayoutInflaterInvoker -> Java LayoutInflater
},
}
At *runtime* when the `LayoutInflaterInvoker` static constructor is
executed, we hit an [assert in the `JniPeerMembers` constructor][0]:
app_process32: ---- DEBUG ASSERTION FAILED ----
app_process32: ---- Assert Short Message ----
app_process32: ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.Views.LayoutInflaterInvoker)).JniTypeName="" != "android/view/LayoutInflater"
app_process32: ---- Assert Long Message ----
app_process32:
app_process32: at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage)
app_process32: at System.Diagnostics.Debug.Fail(String message, String detailMessage)
app_process32: at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage)
app_process32: at System.Diagnostics.Debug.Assert(Boolean condition, String message)
app_process32: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface)
app_process32: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
app_process32: at Android.Runtime.XAPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
app_process32: at Android.Views.LayoutInflaterInvoker..cctor()
app_process32: at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstruct
: CLR: Managed code called FailFast, saying "ManagedPeerType <=> JniTypeName Mismatch! javaVM.GetJniTypeInfoForType(typeof(Android.Views.LayoutInflaterInvoker)).JniTypeName="" != "android/view/LayoutInflater"
: at System.Diagnostics.DebugProvider.Fail(String message, String detailMessage)
: at System.Diagnostics.Debug.Fail(String message, String detailMessage)
: at System.Diagnostics.Debug.Assert(Boolean condition, String message, String detailMessage)
: at System.Diagnostics.Debug.Assert(Boolean condition, String message)
: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType, Boolean checkManagedPeerType, Boolean isInterface)
: at Java.Interop.JniPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
: at Android.Runtime.XAPeerMembers..ctor(String jniPeerTypeName, Type managedPeerType)
: at Android.Views.LayoutInflaterInvoker..cctor()
The cause of the assertion failure is because the `.managed_to_java`
table doesn't contain an entry for `LayoutInflaterInvoker`.
The fix is to modify a017561 behavior and *retain* the `*Invoker`
types in the `.managed_to_java` table:
DebugTypemap = {
.java_to_managed = {
{ "android/view/LayoutInflater", 0 }, // Java LayoutInflater -> C# LayoutInflater
{ "android/view/LayoutInflater", 0 }, // Java LayoutInflater -> C# LayoutInflater
},
.managed_to_java = {
{ "Android.Views.LayoutInflater", 0 }, // C# LayoutInflater -> Java LayoutInflater
{ "Android.Views.LayoutInflaterInvoker", 0 }, // C# LayoutInflaterInvoker -> Java LayoutInflater
},
}
This ensures that we can appropriately obtain a Java type name
for the `LayoutInflaterInvoker` type, fixing the assert.
[0]: https://github.com/xamarin/java.interop/blob/3894cd76f71f618949c8542f0edd95762e22881f/src/Java.Interop/Java.Interop/JniPeerMembers.cs#L29
0 commit comments