Java JNI直接缓冲区。谁负责本机缓冲区释放?
一方面,假设我们使用Java JNI直接缓冲区。谁负责本机缓冲区释放?,java,c,java-native-interface,Java,C,Java Native Interface,一方面,假设我们使用env->NewDirectByteBuffer()创建了一个直接字节缓冲区。另一方面,我们有类似的直接缓冲区,但创建时使用了ByteBuffer.allocateDirect()。显然,JVM应该以相同的方式管理这两个对象,包括管理备份本机缓冲区,在第一种情况下由用户提供,在第二种情况下由JVM从本机堆分配 当然,JVM必须在GC’ing第二个对象(用ByteBuffer.allocateDirect()实例化)期间释放备份缓冲区 我的问题是:JVM会在GC’ing第一个对
env->NewDirectByteBuffer()
创建了一个直接字节缓冲区。另一方面,我们有类似的直接缓冲区,但创建时使用了ByteBuffer.allocateDirect()
。显然,JVM应该以相同的方式管理这两个对象,包括管理备份本机缓冲区,在第一种情况下由用户提供,在第二种情况下由JVM从本机堆分配
当然,JVM必须在GC’ing第二个对象(用ByteBuffer.allocateDirect()实例化)期间释放备份缓冲区
我的问题是:JVM会在GC’ing第一个对象(用env->NewDirectByteBuffer()实例化)期间尝试释放缓冲区吗
另外,我在JNI文档和SO都没有找到明确的答案。最有用的信息如下:
Direct ByteBuffer对象自动清理其本机缓冲区
但是,它们只能作为Java堆GC的一部分来执行,所以它们不能
自动响应本机堆上的压力
所以看起来JVM会在GC传递期间释放备份缓冲区,但并没有提到deallocator。它是普通的free()
还是其他什么。当您调用JNINewDirectByteBuffer(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
的源代码)
现在,cleaner是一个实用程序对象,其clean
方法在缓冲区被垃圾收集时运行(有关详细信息,请参阅此)
对于通过ByteBuffer.allocateDirect()
构建的缓冲区,清理器释放直接内存
对于JNI构造的缓冲区,不执行此类操作。您需要自己释放此内存。清除。看起来安卓也使用同样的方法。Android SDK有详尽的注释:/***表示我们不拥有的内存块。(我们不拥有与JNI NewDirectByteBuffer函数创建的直接缓冲区相对应的*内存。)*/
这是最近最好的QnA之一,似乎没有人知道这一点。