diff --git a/src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalRegisteredPeers.cs b/src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalRegisteredPeers.cs index cf6f550b5fd..18f4ef0aaa9 100644 --- a/src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalRegisteredPeers.cs +++ b/src/Mono.Android/Microsoft.Android.Runtime/JavaMarshalRegisteredPeers.cs @@ -120,10 +120,23 @@ public static void AddPeer (IJavaPeerable value) continue; if (!JniEnvironment.Types.IsSameObject (target.PeerReference, value.PeerReference)) continue; - if (target.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable)) { + // JNIEnv.NewObject/JNIEnv.CreateInstance() compatibility. + // When two MCW's are created for one Java instance [0], + // we want the 2nd MCW to replace the 1st, as the 2nd is + // the one the dev created; the 1st is an implicit intermediary. + // + // Meanwhile, a new "replaceable" instance should *not* replace an + // existing "replaceable" instance; see dotnet/android#9862. + // + // [0]: If Java ctor invokes overridden virtual method, we'll + // transition into managed code w/o a registered instance, and + // thus will create an "intermediary" via + // (IntPtr, JniHandleOwnership) .ctor. + if (target.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable) && + !value.JniManagedPeerState.HasFlag (JniManagedPeerStates.Replaceable)) { peer.Dispose (); peers [i] = new ReferenceTrackingHandle (value); - } else { + } else if (JniEnvironment.Runtime.ObjectReferenceManager.LogGlobalReferenceMessages) { WarnNotReplacing (key, value, target); } GC.KeepAlive (target);