因为它不属于jvm堆& gc,什么时候发布?或者,它一直持续到流程终止?
我已经检查过了:
但是所有答案都很模糊,没有人明确回答,是否有明确的答案?至少对于 64位Linux 上的 Java 8 。
答案 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,您可以获得更多详细信息。