【问题标题】:NewGlobalRef/DeleteGlobalRef when returning object created in JNI返回在 JNI 中创建的对象时的 NewGlobalRef/DeleteGlobalRef
【发布时间】:2015-04-27 09:07:48
【问题描述】:

在将JNI方法中创建的对象的引用返回给Java时,我们应该返回对创建的对象的NewGlobalRef调用的结果吗?并且,分别以后,当Java中不再需要对象时,我们是否需要调用JNI方法对Java传递的引用进行DeleteGlobalRef?

或者 NewGlobalRef/DeleteGlobalRef 只需要在 JNI 中,在 JNI 方法调用之间保存对 Java 对象的引用,如果我们只是将创建的对象返回给 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);
}

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

【问题讨论】:

标签: java android-ndk java-native-interface


【解决方案1】:

在将New[Type]Array,或其他在JNI方法中创建的对象的引用返回给Java时,我们是否应该返回NewGlobalRef对创建的对象的调用结果?

仅当您希望保留该引用以供将来的 JNI 调用使用,而不将其作为 JNI 方法参数再次接收。

然后,当Java不再需要对象时,我们是否需要调用JNI方法对Java传递的引用执行DeleteGlobalRef

只有当你在上面调用NewGlobalRef()

NewGlobalRef/DeleteGlobalRef 只需要在 JNI 中,在 JNI 方法调用之间保存对 Java 对象的引用

完全正确。

如果我们只是简单地将创建的对象返回给 Java,我们就不需要进行NewGlobalRef/DeleteGlobalRef 调用了吗?

再次更正。

我看到在大型开源项目中创建的NewDirectByteBuffer 对象(通过malloc() 分配的实际缓冲区)返回了NewGlobalRef 的结果。后来,当Java不再需要对象时,调用JNI方法,不做DeleteGlobalRef,,而是在从GetDirectBufferAddress.获得的本机缓冲区地址上调用free()

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

【讨论】:

  • 我刚刚回答过了。
  • @Dima 我已经再次回答了这个问题。我不明白你为什么一直问我同样的问题。我也没有提到“实际决定”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 2017-09-24
相关资源
最近更新 更多