假设一方面我们有一个用env->NewDirectByteBuffer()
创建的直接字节缓冲区。另一方面,我们有类似的直接缓冲区,但是使用ByteBuffer.allocateDirect()
创建。显然,这两个对象应该由JVM以相同的方式管理,包括后台本机缓冲区的管理,第一种情况是由用户提供,第二种情况是由JVM从本机堆中分配。
当然,JVM必须在第二个对象的GC期间释放后备缓冲区(用ByteBuffer.allocateDirect()
实例化)。
我的问题是:JVM是否会尝试在第一个对象的GC期间解除分配缓冲区(用env->NewDirectByteBuffer()
实例化)?
P.S。我也没有在JNI医生处找到明确的答案。最有用的信息是http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html:
Direct ByteBuffer对象自动清理其本机缓冲区 但只能作为Java堆GC的一部分这样做 - 所以他们不这样做 自动响应本机堆上的压力。
因此看起来JVM会在GC传递期间释放后备缓冲区,但是没有任何关于deallocator的提及。是free()
还是别的。
答案 0 :(得分:3)
当您调用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
属性为null。
如果您通过DirectByteBuffer
创建ByteBuffer.allocateDirect()
,则会设置cleaner
属性(请参阅DirectByteBuffer
的源代码)。
现在,清理器是一个实用程序对象,当缓冲区被垃圾收集时运行clean
方法(有关详细信息,请参阅此explanation)。
对于通过ByteBuffer.allocateDirect()
构造的缓冲区,清理器释放直接内存。
对于JNI构造的缓冲区,不执行此类操作。你需要自己释放这个记忆。