Releasing a direct buffer in java and possible pitfalls

947 views Asked by At

we have the following piece of code:

long buffer = ((DirectBuffer) ByteBuffer.allocateDirect(256)).address(); 

It seems that there is no reference to direct buffer (as an object) on the thread's stack. So, it means that that object is phantom-reachable.

  • 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.

The citation comes from: Java - When does direct buffer released?

So, it is possible that allocated memory that can be freed. However, we have a pointer to that, buffer of type long. Therefore it is possible that we've got SIGSEGV or something like that.

My question is:

Does it mean that we can hurt ourself using DirectBuffer in that manner?

2

There are 2 answers

0
BeeOnRope On BEST ANSWER

Your assumption of danger here is correct, with a caveat.

The backing buffer of the direct buffer can be freed at any point after the containing ByteBuffer object becomes eligible for garbage collection (the exact moment the native memory is freed is implementation dependent, but typically it happens approximately when finalizer for the ByteBuffer runs).

From standard Java, this "dangling pointer" doesn't pose a real problem since it just a long like another other and you can't use unsafely. Of course if you pass it to some native or Unsafe code and try to use it as a pointer things can blow up.

8
M. le Rutte On

Strictly speaking, not in the exact manner as you described because you just store a long value into a long variable. With this value you can do nothing harmful in Java.

As soon as you pass this to some native (C/C++) code and start using this as the address to write stuff to you get get yourself into problems as the object's memory may already have been reclaimed by the garbage collector.

Therefore all this access should be done in the native code (JNI) where you can use the native API to tell the virtual machine that your native code holds a reference (or not anymore). You can than use the address() function in your native code to get the address and use it.