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);
            }
        }
Ejemplo n.º 2
0
        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();
            }
        }
Ejemplo n.º 3
0
            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);
            }
        }
Ejemplo n.º 5
0
            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));
            }
        }