9

Since it's out of jvm heap & gc, when does it released? Or, it remain until process termination?

I already checked:

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.

Community
  • 1
  • 1
Eric
  • 22,183
  • 20
  • 145
  • 196
  • 1
    When the `ByteBuffer` is garbage collected, the finalizer will execute and release any underlying memory allocation. – Andreas Mar 18 '16 at 06:41
  • Since you don't have the guarantee that it will be freed, I suggest you to take care of it by yourself, I stripped down the [`BufferUtils`](https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/util/BufferUtils.java) class from JM3 for my projects, like [here](https://github.com/elect86/jogl-samples/blob/master/jogl-samples/src/framework/BufferUtils.java), and until now it works flawless – elect Mar 18 '16 at 09:00
  • @elect Yeah, some books also says it's for big & long-live buffers, thus the delay of allocation will have less impact. For small & short-live buffer, it's suggested not to use `direct buffer`, use `indirect buffer` instead. – Eric Mar 18 '16 at 09:07
  • If the resourse is going to be used by OpenGL, buffer must be indirect. If you pass an indirect one, jogl has to create the direct one underneath. So better if it is you creating that, so you can keep track of it. – elect Mar 18 '16 at 09:37
  • @elect Ok, I will keep in mind of existence for such cases. – Eric Mar 18 '16 at 09:51

1 Answers1

28

DirectByteBuffer does not use old Java finalizers. Instead, it uses internal sun.misc.Cleaner API. It creates new thread and stores a PhantomReference to every DirectByteBuffer created (except duplicates and slices which refer to the primary buffer). When the DirectByteBuffer becomes 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 the ReferenceQueue which is processed by Cleaner thread. So three events should occur:

  • DirectByteBuffer becomes phantom-reachable.
  • Garbage collection is performed (in separate thread), DirectByteBuffer Java object is collected and an entry is added to the ReferenceQueue.
  • Cleaner thread reaches this entry and runs the registered clean-up action (in this case, it's java.nio.DirectByteBuffer.Deallocator object), 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 DirectByteBuffer and allocated too much direct memory before, garbage collector might be called explicitly to enforce deallocation of previously abandoned buffers. See Bits.reserveMemory() (called from DirectByteBuffer constructor) for details.

Note that in Java-9 the internal Cleaner API was rectified and published for general use: now it's java.lang.ref.Cleaner. Reading the JavaDoc you may get more details how it works.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334