2016-02-12 165 views
3

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

当然JVM必须在第二个对象的GC_ing过程中释放后台缓冲区(用ByteBuffer.allocateDirect()实例化)。

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

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

直接ByteBuffer对象会自动清理自己的本地缓存 但只能做这么为Java堆GC的一部分 - 所以他们不 自动应对压力本机堆。

所以看起来JVM会在GC传递过程中释放后台缓冲区,但是没有任何关于释放器的提及。是平原free()还是别的什么。

回答

2

当你调用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。

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

现在清洁器是一个实用程序对象,其clean方法当缓冲器是垃圾收集运行(参见本explanation细节)。

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

对于JNI构造的缓冲区,没有这样的操作完成。你需要自己释放这个记忆。

+0

清除。看起来像Android使用相同的方法。 Android SDK详尽评论:'/ ** *表示我们不拥有的一块内存。 (我们没有取得对应于 *的内存的所有权来指导由JNI NewDirectByteBuffer函数创建的缓冲区。) * /' – Sergio