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构造的缓冲区没有进行这样的操作。您需要自己释放此内存。
一方面假设我们有一个使用 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构造的缓冲区没有进行这样的操作。您需要自己释放此内存。