internal jvmtiError AddGlobalReference(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jobject obj) { long tag; jvmtiError error = environment.GetTag(obj, out tag); if (error != jvmtiError.None) { return(error); } if (tag == 0) { return(jvmtiError.IllegalArgument); } _globalReferences.AddOrUpdate(tag, t => { return(Tuple.Create(nativeEnvironment.NewGlobalReference(obj), 1)); }, (t, v) => { if (v.Item2 == 0) { return(Tuple.Create(nativeEnvironment.NewGlobalReference(obj), 1)); } else { return(Tuple.Create(v.Item1, v.Item2 + 1)); } }); return(jvmtiError.None); }
internal jvmtiError RemoveGlobalReference(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jobject obj) { long tag; jvmtiError error = environment.GetTag(obj, out tag); if (error != jvmtiError.None) { return(error); } if (tag == 0) { return(jvmtiError.IllegalArgument); } var result = _globalReferences.AddOrUpdate(tag, t => { return(Tuple.Create(jobject.Null, 0)); }, (t, v) => { if (v.Item2 == 0) { return(Tuple.Create(jobject.Null, 0)); } else if (v.Item2 == 1) { nativeEnvironment.DeleteGlobalReference(v.Item1); return(Tuple.Create(jobject.Null, 0)); } else { return(Tuple.Create(v.Item1, v.Item2 - 1)); } }); return(jvmtiError.None); }
internal TaggedObjectId TrackLocalObjectReference(jobject @object, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, bool freeLocalReference) { if (@object == jobject.Null) { return(new TaggedObjectId(Tag.Object, new ObjectId(0), default(TaggedReferenceTypeId))); } long tag; JvmtiErrorHandler.ThrowOnFailure(environment.GetTag(@object, out tag)); TaggedReferenceTypeId type = default(TaggedReferenceTypeId); Tag objectKind; if (tag == 0) { long uniqueTag = Interlocked.Increment(ref _nextTag); /* first figure out what type of object we're dealing with. could be: * - String * - Thread * - ThreadGroup * - ClassLoader * - ClassObject * - Array * - Object */ // check for array jclass objectClass = nativeEnvironment.GetObjectClass(@object); try { type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, false); bool isArray = type.TypeTag == TypeTag.Array; if (isArray) { objectKind = Tag.Array; } else { if (_stringClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _stringClass)) { objectKind = Tag.String; } else if (_threadClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadClass)) { objectKind = Tag.Thread; } else if (_threadGroupClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadGroupClass)) { objectKind = Tag.ThreadGroup; } else if (_classClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classClass)) { objectKind = Tag.ClassObject; } else if (_classLoaderClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classLoaderClass)) { objectKind = Tag.ClassLoader; } else { objectKind = Tag.Object; } } } finally { nativeEnvironment.DeleteLocalReference(objectClass); } tag = (uniqueTag << 8) | (uint)objectKind; JvmtiErrorHandler.ThrowOnFailure(environment.SetTag(@object, tag)); lock (_objects) { _objects.Add(new ObjectId(tag), nativeEnvironment.NewWeakGlobalReference(@object)); } } else { jclass objectClass = nativeEnvironment.GetObjectClass(@object); type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, true); } if (freeLocalReference) { nativeEnvironment.DeleteLocalReference(@object); } objectKind = (Tag)(tag & 0xFF); return(new TaggedObjectId(objectKind, new ObjectId(tag), type)); }