Java - 何时释放直接缓冲区?

时间:2016-03-18 06:33:03

标签: java nio bytebuffer direct-buffer

因为它不属于jvm堆& gc,什么时候发布?或者,它一直持续到流程终止?

我已经检查过了:

但是所有答案都很模糊,没有人明确回答,是否有明确的答案?至少对于 64位Linux 上的 Java 8

1 个答案:

答案 0 :(得分:19)

DirectByteBuffer不使用旧的Java终结器。相反,它使用内部sun.misc.Cleaner API。它创建新线程并为创建的每个PhantomReference存储DirectByteBuffer(除了指向主缓冲区的重复和切片)。当DirectByteBuffer变为幻像可达(即,不再存在对字节缓冲区的强,弱或弱引用)并且垃圾收集器看到此情况时,它会将此缓冲区添加到{{ 1}}由ReferenceQueue线程处理。所以应该发生三件事:

  • Cleaner变为幻影可达。
  • 执行垃圾收集(在单独的线程中),DirectByteBuffer收集Java对象并将条目添加到DirectByteBuffer
  • 清理线程到达此条目并运行已注册的清理操作(在本例中为ReferenceQueue对象),此操作最终释放本机内存。

因此,一般情况下,您无法保证何时获释。如果Java堆中有足够的内存,则可能无法长时间激活垃圾收集器。即使它的幻像可达,Cleaner线程也可能需要一些时间才能达到此条目。它可能正在忙于处理也使用Cleaner API的先前对象。但请注意,部分解决方法是在JDK中实现的:如果您之前创建了新的java.nio.DirectByteBuffer.Deallocator并分配了太多的直接内存,则可能会显式调用垃圾收集器以强制释放先前放弃的缓冲区。有关详细信息,请参阅Bits.reserveMemory()(从DirectByteBuffer构造函数调用)。

请注意,在Java-9中,内部DirectByteBuffer API已得到纠正并发布以供一般使用:现在它是java.lang.ref.Cleaner。阅读JavaDoc,您可以获得更多详细信息。