Exemple #1
0
        internal static void AssertSelf(IJavaPeerable self)
        {
            if (self == null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            var peer = self.PeerReference;

            if (!peer.IsValid)
            {
                throw new ObjectDisposedException(self.GetType().FullName);
            }

#if FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES
            var lref = peer.SafeHandle as JniLocalReference;
            if (lref != null && !JniEnvironment.IsHandleValid(lref))
            {
                var t = self.GetType().FullName;
                throw new NotSupportedException(
                          "You've created a " + t + " in one thread and are using it " +
                          "from another thread without calling IJavaPeerable.Register(). " +
                          "Passing JNI local references between threads is not supported; " +
                          "call IJavaObject.RegisterWithVM() if sharing between threads is required.");
            }
#endif  // FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES
        }
        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);
            }
        }
Exemple #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);
            }
        }
Exemple #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);
                }
            }
        protected override bool UsesVirtualDispatch(IJavaPeerable value, Type declaringType)
        {
            var peerType  = GetThresholdType (value);
            if (peerType != null) {
                return peerType == value.GetType ();
            }

            return base.UsesVirtualDispatch (value, declaringType);
        }
Exemple #7
0
        protected override bool UsesVirtualDispatch(IJavaPeerable value, Type declaringType)
        {
            var peerType = GetThresholdType(value);

            if (peerType != null)
            {
                return(peerType == value.GetType());
            }

            return(base.UsesVirtualDispatch(value, declaringType));
        }
        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");
            }
        }
 void WarnNotReplacing(int key, IJavaPeerable ignoreValue, IJavaPeerable keepValue)
 {
     Runtime.ObjectReferenceManager.WriteGlobalReferenceLine(
         "Warning: Not registering PeerReference={0} IdentityHashCode=0x{1} Instance={2} Instance.Type={3} Java.Type={4}; " +
         "keeping previously registered PeerReference={5} Instance={6} Instance.Type={7} Java.Type={8}.",
         ignoreValue.PeerReference.ToString(),
         key.ToString("x"),
         RuntimeHelpers.GetHashCode(ignoreValue).ToString("x"),
         ignoreValue.GetType().FullName,
         JniEnvironment.Types.GetJniTypeNameFromInstance(ignoreValue.PeerReference),
         keepValue.PeerReference.ToString(),
         RuntimeHelpers.GetHashCode(keepValue).ToString("x"),
         keepValue.GetType().FullName,
         JniEnvironment.Types.GetJniTypeNameFromInstance(keepValue.PeerReference));
 }
            public unsafe void FinishCreateInstance(string constructorSignature, IJavaPeerable self, JniArgumentValue *parameters)
            {
                if (constructorSignature == null)
                {
                    throw new ArgumentNullException(nameof(constructorSignature));
                }
                if (self == null)
                {
                    throw new ArgumentNullException(nameof(self));
                }

                if (JniEnvironment.Runtime.NewObjectRequired)
                {
                    return;
                }
                var methods = GetConstructorsForType(self.GetType());
                var ctor    = methods.GetConstructor(constructorSignature);

                JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod(self.PeerReference, methods.JniPeerType.PeerReference, ctor, parameters);
            }
Exemple #11
0
 protected virtual bool UsesVirtualDispatch(IJavaPeerable value, Type?declaringType)
 {
     return(value.GetType() == declaringType ||
            declaringType == null ||
            value.GetType() == value.JniPeerMembers.ManagedPeerType);
 }
        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));
            }
        }