0

一段时间以来一直在 NDK 端使用 java.nio.ByteBuffers - 注意到这篇关于 Android 与 JNI、GC 和 ICS 未来的关系的文章。文章在这里http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html

所以......这是关注点:

由于 JNI 提供的“指针”实际上似乎是由 JNI 内部管理的引用 - 如果在传递之前未在 JNI 方法中将其标记为 NewGlobalReference(),则它可能会在某个时候被 GC“移动”或删除到 C++ 类?

在我的 JNI 方法中,我获取直接缓冲区地址并将其传递给使用它的类,而无需任何

env->NewGlobalRef(jobject); 
env->NewLocalRef(jobject); 
env->DeleteGlobalRef(jobject); 

管理。

现在一切正常 - 但它正确吗?

想法?

PS - 我确实在 C++ 的退出/析构函数上使用了 free(ByteBuffer)

4

2 回答 2

2

本地引用仅在它被传递到或在其中创建的 JNI 方法的持续时间内有效。在该方法返回 JVM 后,该引用不再有效。如果您不违反该规则,那您就可以了。

于 2013-06-25T21:43:15.877 回答
0

有点不清楚你在问什么,所以让我试着澄清几点。

您在 JNI 中获得的任何jobject类型,无论是从 JNI 调用中返回FindClass还是作为参数(jobjectjclassjbyteArray等)传入,都是本地引用。它的寿命很短。如果你将它传递给NewGlobalRef,你会得到一个全局引用作为回报;这将持续到您将其删除。

任何采用或返回指针类型的 JNI 函数都会为您提供一个很好的指针,直到某些东西使其无效为止。例如,如果你调用GetStringUTFChars,你会得到一个const char*在你调用之前有效的ReleaseStringUTFChars

引用不是指针,指针也不是引用。您不能传递char*to NewGlobalRef,也不能取消引用全局引用(其中“不能”通常是错误或本机崩溃)。

我假设你正在做的是调用GetDirectByteBufferAddress一个ByteBuffer对象,它返回一个void*指向直接字节缓冲区开始的对象。该指针在存储空间被释放之前一直有效。如何发生取决于您如何分配它:

  • 如果您使用 分配了直接字节缓冲区ByteBuffer.allocateDirect(),则 Dalvik 拥有存储空间。ByteBuffer当变得无法访问并被垃圾收集时,它将被释放。
  • 如果您自己分配了存储空间,并将其与ByteBufferJNINewDirectByteBuffer调用相关联,那么它在您释放它之前一直有效。

对于这种allocateDirect()情况,在托管代码丢弃ByteBuffer. 一种方法是ByteBuffer在本机代码中保留对 的全局引用,并在删除全局引用的同时使缓冲区指针无效。取决于您的代码的结构,这可能不是必需的。

另请参阅JNI 提示页面。

于 2013-06-26T22:52:53.977 回答