public void Construct(IJavaPeerable peer, ref JniObjectReference reference, JniObjectReferenceOptions options) { if (peer == null) { throw new ArgumentNullException(nameof(peer)); } var newRef = peer.PeerReference; if (newRef.IsValid) { // Activation! See ManagedPeer.RunConstructor peer.SetJniManagedPeerState(peer.JniManagedPeerState | JniManagedPeerStates.Activatable); JniObjectReference.Dispose(ref reference, options); newRef = newRef.NewGlobalRef(); } else if (options == JniObjectReferenceOptions.None) { // `reference` is likely *InvalidJniObjectReference, and can't be touched return; } else if (!reference.IsValid) { throw new ArgumentException("JNI Object Reference is invalid.", nameof(reference)); } else { newRef = reference; if ((options & JniObjectReferenceOptions.Copy) == JniObjectReferenceOptions.Copy) { newRef = reference.NewGlobalRef(); } JniObjectReference.Dispose(ref reference, options); } peer.SetPeerReference(newRef); peer.SetJniIdentityHashCode(JniSystem.IdentityHashCode(newRef)); var o = Runtime.ObjectReferenceManager; if (o.LogGlobalReferenceMessages) { o.WriteGlobalReferenceLine("Created PeerReference={0} IdentityHashCode=0x{1} Instance=0x{2} Instance.Type={3}, Java.Type={4}", newRef.ToString(), peer.JniIdentityHashCode.ToString("x"), RuntimeHelpers.GetHashCode(peer).ToString("x"), peer.GetType().FullName, JniEnvironment.Types.GetJniTypeNameFromInstance(newRef)); } if ((options & DoNotRegisterTarget) != DoNotRegisterTarget) { Add(peer); } }
internal void AddPeer(IJavaPeerable value, IntPtr handle, JniHandleOwnership transfer, out IntPtr handleField) { if (handle == IntPtr.Zero) { handleField = handle; return; } var transferType = transfer & (JniHandleOwnership.DoNotTransfer | JniHandleOwnership.TransferLocalRef | JniHandleOwnership.TransferGlobalRef); switch (transferType) { case JniHandleOwnership.DoNotTransfer: handleField = JNIEnv.NewGlobalRef(handle); break; case JniHandleOwnership.TransferLocalRef: handleField = JNIEnv.NewGlobalRef(handle); JNIEnv.DeleteLocalRef(handle); break; case JniHandleOwnership.TransferGlobalRef: handleField = handle; break; default: throw new ArgumentOutOfRangeException("transfer", transfer, "Invalid `transfer` value: " + transfer + " on type " + value.GetType()); } if (handleField == IntPtr.Zero) { throw new InvalidOperationException("Unable to allocate Global Reference for object '" + value.ToString() + "'!"); } IntPtr hash = JNIEnv.IdentityHash !(handleField); value.SetJniIdentityHashCode((int)hash); if ((transfer & JniHandleOwnership.DoNotRegister) == 0) { AddPeer(value, new JniObjectReference(handleField, JniObjectReferenceType.Global), hash); } if (Logger.LogGlobalRef) { JNIEnv._monodroid_gref_log("handle 0x" + handleField.ToString("x") + "; key_handle 0x" + hash.ToString("x") + ": Java Type: `" + JNIEnv.GetClassNameFromInstance(handleField) + "`; " + "MCW type: `" + value.GetType().FullName + "`\n"); } }