Java - 什么时候释放直接缓冲区?

Java - When does direct buffer released?

既然已经脱离了jvm heap & gc,那么什么时候释放呢?或者,它一直保留到进程终止?

我已经检查过:

但是所有的答案都是模糊的,none回答的很明确,有明确的答案吗?至少 Java 8 64 位 Linux.

DirectByteBuffer 不使用旧的 Java 终结器。相反,它使用内部 sun.misc.Cleaner API。它创建新线程并将 PhantomReference 存储到每个创建的 DirectByteBuffer (引用主缓冲区的副本和切片除外)。当 DirectByteBuffer 变为 phantom-reachable(即不再存在对字节缓冲区的强引用、软引用或弱引用)并且垃圾收集器看到这一点时,它将此缓冲区添加到ReferenceQueueCleaner 线程处理。所以应该发生三个事件:

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

所以一般来说你不能保证它什么时候被释放。如果你在Java堆中有足够的内存,垃圾收集器可能很长时间都不会被激活。此外,即使它是幻影可达的,Cleaner 线程也可能需要一些时间才能到达此条目。它可能正忙于处理以前也使用了 Cleaner API 的对象。但是请注意,JDK 中实现了部分变通方法:如果您创建新的 DirectByteBuffer 并且之前分配了过多的直接内存,则可能会显式调用垃圾收集器以强制释放先前放弃的缓冲区。有关详细信息,请参阅 Bits.reserveMemory()(从 DirectByteBuffer 构造函数调用)。

请注意,在 Java-9 中,内部 Cleaner API 已更正并发布以供一般使用:现在是 java.lang.ref.Cleaner。阅读 Java 文档,您可能会了解其工作原理的更多详细信息。