我必须 DeleteLocalRef 一个我调用了 NewGlobalRef 的对象吗?

Must I DeleteLocalRef an object I have called NewGlobalRef on?

我们知道,在 C/C++ 拥有的线程中创建 Java 个对象,我们负责根据需要调用 DeleteLocalRefPush/Pop LocalFrame

我有一些代码,例如

jbyteArray buffer = env->NewByteArray((jsize)requiredSize);
longTermBufferReference = (jbyteArray)env->NewGlobalRef(buffer);

本机代码创建一个字节数组,它在多个 threads/calls 中重复使用,完成后,我在缓冲区上调用 DeleteGlobalRef

问题是,完成后我必须在 buffer 上调用 DeleteLocalRef,还是 GlobalRef 会完全拥有该对象?

The question is, must I call DeleteLocalRef on buffer when I'm done

不,您可以让它在您的 JNI 方法 returns 时自动删除,或者如果您使用它,则由 PopLocalFrame() 自动删除。但是本地引用是一种稀缺资源:如果你的 JNI 函数使用了很多,你应该尽快释放它们。

补充一下@EJP 所说的:只有当不再有(强)引用时,对象才有资格进行垃圾回收。当您执行 NewGlobalRef 时,您创建了对对象的第二个引用,将引用数量增加到 2。本地引用仍将存在。

当你的函数退出时它会被运行时删除,但假设你的函数很长。如果您调用 DeleteGlobalRef,您将删除全局引用,但局部引用仍不受影响。引用数:1。只有在删除这个之后,垃圾收集器才能声明该对象。

在垃圾收集系统中,没有对象所有权这样的东西。存在根对象引用和可从根直接或间接到达的对象引用。 (不考虑弱引用)。

JNI 局部引用和JNI 全局引用都是根引用。创建其他引用不会影响现有引用,也不会将它们从根引用列表中删除。

所以,是的,必须删除本地引用(就像必须删除全局引用一样)。您已经知道可以使用 DeleteLocalRefPopLocalFrame 显式执行此操作,或者,当 JNI 本机方法 returns 时,JNI 会有效地自动调用 PopLocalFrame