JNI 直接缓冲区。谁负责本机缓冲区释放?

JNI direct buffers. Who is responsible for native buffer freeing?

一方面假设我们有一个使用 env->NewDirectByteBuffer() 创建的直接字节缓冲区。另一方面,我们有类似的直接缓冲区,但使用 ByteBuffer.allocateDirect() 创建。显然,这两个对象都应该由 JVM 以相同的方式管理,包括支持本机缓冲区的管理,在第一种情况下由用户提供,在第二种情况下由 JVM 从本机堆中分配。

当然,JVM 必须在第二个对象的 GC 期间释放后备缓冲区(用 ByteBuffer.allocateDirect() 实例化)。

我的问题是:JVM 会在第一个对象(用 env->NewDirectByteBuffer() 实例化)的 GC 期间尝试释放缓冲区吗?

P.S。我在 JNI 文档和 SO 都没有找到明确的答案。最有用的信息在这里 http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html :

Direct ByteBuffer objects clean up their native buffers automatically but can only do so as part of Java heap GC — so they do not automatically respond to pressure on the native heap.

所以 JVM 似乎会在 GC 传递期间释放后备缓冲区,但没有任何关于 deallocator 的提及。是普通的 free() 还是其他的。

当您调用 JNI NewDirectByteBuffer(void* address, jlong capacity) 时,将使用以下构造函数创建一个 DirectByteBuffer 对象:

private DirectByteBuffer(long addr, int cap) {
    super(-1, 0, cap, cap);
    address = addr;
    cleaner = null;
    att = null;
}

请注意 cleaner 属性 为空。

如果您通过 ByteBuffer.allocateDirect() 创建 DirectByteBuffer,则会设置 cleaner 属性(参见 DirectByteBuffer 的源代码)。

现在清理器是一个实用对象,当缓冲区被垃圾收集时,其 clean 方法是 运行(有关详细信息,请参阅此 explanation)。

对于通过 ByteBuffer.allocateDirect() 构造的缓冲区,清理器释放直接内存。

对于JNI构造的缓冲区没有进行这样的操作。您需要自己释放此内存。