NewGlobalRef/DeleteGlobalRef 当返回在 JNI 中创建的对象时

NewGlobalRef/DeleteGlobalRef when returning object created in JNI

当 return 将 JNI 方法中创建的对象的引用引用到 Java 时,我们是否应该 return NewGlobalRef 调用创建的对象的结果?并且,稍后,当 Java 中不再需要对象时,我们是否需要调用 JNI 方法对从 Java 传递的引用执行 DeleteGlobalRef?

或者 NewGlobalRef/DeleteGlobalRef 只需要在 JNI 方法调用之间保存对 Java 对象的引用,如果我们只是 return 创建对象到 Java 我们不需要需要打 NewGlobalRef/DeleteGlobalRef 个电话?

我在一个大型开源项目中看到过这样的事情:

extern "C" JNIEXPORT jobject JNICALL
Java_foo_bar_Baz_create(JNIEnv* env, jclass, jint size) {
    void* buf = malloc(size);
    jobject obj = env->NewDirectByteBuffer(buf, size);
    return env->NewGlobalRef(obj);
}

extern "C" JNIEXPORT void JNICALL
Java_foo_bar_Baz_free(JNIEnv* env, jclass, jobject jbuffer) {
    void* buf = env->GetDirectBufferAddress(jbuffer);        
    free(buf);
}

它 return NewGlobalRef 调用创建的 NewDirectByteBuffer 对象的结果,后来,当 Java 中不再需要对象时,调用不调用 DeleteGlobalRef 的 JNI 方法,但只是在本机缓冲区地址上调用 free()。

When returning reference to New[Type]Array, or other object created in JNI method to Java, should we return result of NewGlobalRef call on created object?

仅当您想要保留该引用以供将来的 JNI 调用使用而无需再次将其作为 JNI 方法参数接收时。

And respectively, later, when object no more required in Java, do we need to call JNI method to do DeleteGlobalRef on the reference passed from Java?

仅当您在其上调用 NewGlobalRef() 时。

Or NewGlobalRef/DeleteGlobalRef required only to hold references to Java object inside JNI, between JNI methods calls

完全正确。

and if we simply return created object to Java we dont need to do NewGlobalRef/DeleteGlobalRef calls?

再次更正。

I saw returning result of NewGlobalRef on created NewDirectByteBuffer object (real buffer allocated via malloc()), in large open source project. And later, when object no more required in Java, there is a call to JNI method, that don't do DeleteGlobalRef, but just call free() on the native buffer address obtained from GetDirectBufferAddress.

这将构成 DirectByteBuffer 对象的泄漏,但不会构成其本机缓冲区的泄漏。