public override void FinalizePeer(IJavaPeerable value) { var h = value.PeerReference; var o = Runtime.ObjectReferenceManager; // MUST NOT use SafeHandle.ReferenceType: local refs are tied to a JniEnvironment // and the JniEnvironment's corresponding thread; it's a thread-local value. // Accessing SafeHandle.ReferenceType won't kill anything (so far...), but // instead it always returns JniReferenceType.Invalid. if (!h.IsValid || h.Type == JniObjectReferenceType.Local) { if (o.LogGlobalReferenceMessages) { o.WriteGlobalReferenceLine("Finalizing PeerReference={0} IdentityHashCode=0x{1} Instance=0x{2} Instance.Type={3}", h.ToString(), value.JniIdentityHashCode.ToString("x"), RuntimeHelpers.GetHashCode(value).ToString("x"), value.GetType().ToString()); } RemovePeer(value); value.SetPeerReference(new JniObjectReference()); value.Finalized(); return; } try { bool collected = TryGC(value, ref h); if (collected) { RemovePeer(value); value.SetPeerReference(new JniObjectReference()); if (o.LogGlobalReferenceMessages) { o.WriteGlobalReferenceLine("Finalizing PeerReference={0} IdentityHashCode=0x{1} Instance=0x{2} Instance.Type={3}", h.ToString(), value.JniIdentityHashCode.ToString("x"), RuntimeHelpers.GetHashCode(value).ToString("x"), value.GetType().ToString()); } value.Finalized(); } else { value.SetPeerReference(h); GC.ReRegisterForFinalize(value); } } catch (Exception e) { Runtime.FailFast("Unable to perform a GC! " + e); } }
public override void FinalizePeer(IJavaPeerable value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (Logger.LogGlobalRef) { JNIEnv._monodroid_gref_log($"Finalizing handle {value.PeerReference}\n"); } // FIXME: need hash cleanup mechanism. // Finalization occurs after a test of java persistence. If the // handle still contains a java reference, we can't finalize the // object and should "resurrect" it. if (value.PeerReference.IsValid) { GC.ReRegisterForFinalize(value); } else { RemovePeer(value, (IntPtr)value.JniIdentityHashCode); value.SetPeerReference(new JniObjectReference()); value.Finalized(); } }
void Dispose(JniObjectReference h, IJavaPeerable value) { value.Disposed(); Remove(value); var o = Runtime.ObjectReferenceManager; if (o.LogGlobalReferenceMessages) { o.WriteGlobalReferenceLine("Disposing PeerReference={0} IdentityHashCode=0x{1} Instance=0x{2} Instance.Type={3} Java.Type={4}", h.ToString(), value.JniIdentityHashCode.ToString("x"), RuntimeHelpers.GetHashCode(value).ToString("x"), value.GetType().ToString(), JniEnvironment.Types.GetJniTypeNameFromInstance(h)); } #if FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES var lref = value.PeerReference.SafeHandle as JniLocalReference; if (lref != null && !JniEnvironment.IsHandleValid(lref)) { // `lref` was created on another thread, and CANNOT be disposed on this thread. // Just invalidate the reference and move on. lref.SetHandleAsInvalid(); } #endif // FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES JniObjectReference.Dispose(ref h); value.SetPeerReference(new JniObjectReference()); GC.SuppressFinalize(value); }
public override void AddPeer(IJavaPeerable value) { if (RegisteredInstances == null) { throw new ObjectDisposedException(nameof(MonoRuntimeValueManager)); } var r = value.PeerReference; if (!r.IsValid) { throw new ObjectDisposedException(value.GetType().FullName); } var o = PeekPeer(value.PeerReference); if (o != null) { return; } if (r.Type != JniObjectReferenceType.Global) { value.SetPeerReference(r.NewGlobalRef()); JniObjectReference.Dispose(ref r, JniObjectReferenceOptions.CopyAndDispose); } int key = value.JniIdentityHashCode; lock (RegisteredInstances) { List <IJavaPeerable> peers; if (!RegisteredInstances.TryGetValue(key, out peers)) { peers = new List <IJavaPeerable> () { value, }; RegisteredInstances.Add(key, peers); return; } for (int i = peers.Count - 1; i >= 0; i--) { var p = peers [i]; if (!JniEnvironment.Types.IsSameObject(p.PeerReference, value.PeerReference)) { continue; } if (Replaceable(p)) { peers [i] = value; } else { WarnNotReplacing(key, value, p); } return; } peers.Add(value); } }
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); } }
public override void AddPeer(IJavaPeerable value) { var r = value.PeerReference; if (!r.IsValid) { throw new ObjectDisposedException(value.GetType().FullName); } var o = PeekPeer(value.PeerReference); if (o != null) { return; } if (r.Type != JniObjectReferenceType.Global) { value.SetPeerReference(r.NewGlobalRef()); JniObjectReference.Dispose(ref r, JniObjectReferenceOptions.CopyAndDispose); } int key = value.JniIdentityHashCode; lock (RegisteredInstances) { List <WeakReference <IJavaPeerable> > peers; if (!RegisteredInstances.TryGetValue(key, out peers)) { peers = new List <WeakReference <IJavaPeerable> > () { new WeakReference <IJavaPeerable>(value, trackResurrection: true), }; RegisteredInstances.Add(key, peers); return; } for (int i = peers.Count - 1; i >= 0; i--) { var wp = peers [i]; IJavaPeerable p; if (!wp.TryGetTarget(out p)) { // Peer was collected peers.RemoveAt(i); continue; } if (!JniEnvironment.Types.IsSameObject(p.PeerReference, value.PeerReference)) { continue; } if (Replaceable(p)) { peers [i] = new WeakReference <IJavaPeerable>(value, trackResurrection: true); } else { WarnNotReplacing(key, value, p); } return; } peers.Add(new WeakReference <IJavaPeerable> (value, trackResurrection: true)); } }