Since it's out of jvm heap & gc, when does it released? Or, it remain until process termination?
I already checked:
- how to garbage collect a direct buffer java
- Deallocating Direct Buffer Native Memory in Java for JOGL
- ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()
But all the answers are blur, none answered it explicitly, does there have a clear answer? At least for Java 8 on 64-bit Linux.
DirectByteBufferdoes not use old Java finalizers. Instead, it uses internalsun.misc.CleanerAPI. It creates new thread and stores aPhantomReferenceto everyDirectByteBuffercreated (except duplicates and slices which refer to the primary buffer). When theDirectByteBufferbecomes phantom-reachable (that is, no strong, soft or weak references to the byte buffer exist anymore) and garbage collector sees this, it adds this buffer to theReferenceQueuewhich is processed byCleanerthread. So three events should occur:DirectByteBufferbecomes phantom-reachable.DirectByteBufferJava object is collected and an entry is added to theReferenceQueue.java.nio.DirectByteBuffer.Deallocatorobject), this action finally frees the native memory.So in general you have no guarantee when it's freed. If you have enough memory in the Java heap, garbage collector may not be activated for a long time. Also even when it's phantom-reachable, Cleaner thread may need some time to reach this entry. It might be busy processing previous objects which also used the Cleaner API. Note however that partial work-around is implemented in JDK: if you create new
DirectByteBufferand allocated too much direct memory before, garbage collector might be called explicitly to enforce deallocation of previously abandoned buffers. SeeBits.reserveMemory()(called fromDirectByteBufferconstructor) for details.Note that in Java-9 the internal
CleanerAPI was rectified and published for general use: now it'sjava.lang.ref.Cleaner. Reading the JavaDoc you may get more details how it works.