如果调用 JNI DeleteGlobalRef(),相应的 java 对象是否会被垃圾回收?

2022-09-04 21:01:40

我的意思是,如果我在C++中创建一个全局引用 jobject,然后将其传递给一些 Java 代码,并删除调用 DeleteGlobalRef(),那么该底层 Java 对象是否会立即被垃圾回收,以便任何已经引用该对象的未来 Java 代码都可能返回 NullPointerException?具体来说,如果我有一些C++代码可以执行如下简化示例:

static jobject myObjGlobalRef;
static JNIEnv* env = /* call to create a JVM and get the JNI env */;
jobject ReturnMyObj()
{
    /* <<Code that defines class, constructorId, and param1 goes here>> */

    jobject localObj = env->NewObject(class, constructorId, param1);
    myObjGlobalRef = env->NewGlobalRef(localObj);
}

void DeleteMyObj()
{
    env->DeleteGlobalRef(myObjGlobalRef);
}

myObjGlobalRef = ReturnMyObj();

jobject otherExistingGlobalRef = /* Assume we get another global ref to another parent obj somewhere else */
/*  ... other code here ... */
// Invoke some method on some other pre-existing global reference that uses
// myObjGlobalRef,  lets assume this method stores the object referenced by
// myObjGlobalRef into a parent object referenced by otherExistingGlobalRef:
env->CallVoidMethod(env, otherExistingGlobalRef, addASubObjectMethodId, myObjGlobalRef);

DeleteMyObj();

// Does the pointed to by myObjGlobalRef still exist here, assuming that
// otherExistingGlobalRef now references it?

这在JNI中是如何工作的?对象上的“GlobalReference”是否只是对该对象的引用计数,因此如果我释放GlobalReference jobject,它不一定会对底层java对象进行垃圾回收,直到所有对它的引用(例如“父”对象otherExistingGlobalRef引用它)都消失了?

如果你能回答这个问题,并提供一些官方Java / Sun / Oracle文档的链接来支持你的答案,你将获得奖金:-)。


答案 1

DeleteGlobalRef() 释放引用,而不是对象。

如果这是最后一个可访问的引用,则引用的对象可用于垃圾回收。

对象上的“全局引用”只是对对象的引用计数

哈哈它只是一个引用,在您显式释放它之前保持有效。Java的垃圾回收根本不依赖于引用计数。

另请参阅 Oracle 关于全局参考的文档


答案 2

推荐