Java - 什么时候释放直接缓冲区?
Java - When does direct buffer released?
既然已经脱离了jvm heap & gc,那么什么时候释放呢?或者,它一直保留到进程终止?
我已经检查过:
- how to garbage collect a direct buffer java
- Deallocating Direct Buffer Native Memory in Java for JOGL
- ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()
但是所有的答案都是模糊的,none回答的很明确,有明确的答案吗?至少 Java 8 64 位 Linux.
DirectByteBuffer
不使用旧的 Java 终结器。相反,它使用内部 sun.misc.Cleaner
API。它创建新线程并将 PhantomReference
存储到每个创建的 DirectByteBuffer
(引用主缓冲区的副本和切片除外)。当 DirectByteBuffer
变为 phantom-reachable(即不再存在对字节缓冲区的强引用、软引用或弱引用)并且垃圾收集器看到这一点时,它将此缓冲区添加到ReferenceQueue
由 Cleaner
线程处理。所以应该发生三个事件:
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 文档,您可能会了解其工作原理的更多详细信息。
既然已经脱离了jvm heap & gc,那么什么时候释放呢?或者,它一直保留到进程终止?
我已经检查过:
- how to garbage collect a direct buffer java
- Deallocating Direct Buffer Native Memory in Java for JOGL
- ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()
但是所有的答案都是模糊的,none回答的很明确,有明确的答案吗?至少 Java 8 64 位 Linux.
DirectByteBuffer
不使用旧的 Java 终结器。相反,它使用内部 sun.misc.Cleaner
API。它创建新线程并将 PhantomReference
存储到每个创建的 DirectByteBuffer
(引用主缓冲区的副本和切片除外)。当 DirectByteBuffer
变为 phantom-reachable(即不再存在对字节缓冲区的强引用、软引用或弱引用)并且垃圾收集器看到这一点时,它将此缓冲区添加到ReferenceQueue
由 Cleaner
线程处理。所以应该发生三个事件:
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 文档,您可能会了解其工作原理的更多详细信息。