1

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?

Gilgamesz
  • 4,727
  • 3
  • 28
  • 63
  • Well, you're treading on thin ice using `sun.nio.ch.DirectBuffer` in your code. As an implementation class in the `sun.*` hierarchy there's no guarantee it will be available in a future release. So I guess the answer is probably "yes, you can hurt yourself". You really need to explain why you want to do this. According to the comments the `address` field is there to optimize a JNI call. Besides physical addresses have no meaning or value in Java code. – Jim Garrison Apr 21 '18 at 19:32

2 Answers2

1

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.

BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
-1

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.

M. le Rutte
  • 3,525
  • 3
  • 18
  • 31
  • but long is not a reference type. I'me pretty sure that it doesn't matter for a garbage collector. – Gilgamesz Apr 21 '18 at 19:46
  • That is *exactly* what I wrote in the first sentence. – M. le Rutte Apr 21 '18 at 20:18
  • How does garbage collector know that `DirectBuffer` object is alive? – Gilgamesz Apr 21 '18 at 20:28
  • I think there is a SO answer on that topic. Summary: as long as it is reachable from a point on the thread's stack. As soon as you move into native that rule doesn't apply anymore and you have to help the VM out. – M. le Rutte Apr 21 '18 at 20:31
  • But, `DirectBuffer object` is unreachable so it can be released. Address of backed memory is reachable but object is not. This is why I think it can be collected. "As soon as you move into native that rule doesn't apply anymore and you have to help the VM out". By the way, how to? – Gilgamesz Apr 21 '18 at 20:35
  • In your code the `DirectBuffer` is reachable at least until the assignment is done, at which point it is just a long value, which means nothing. To interpret it as an address is not in Java. For more information on how to do JNI check out [Oracle's trail on JNI](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html) – M. le Rutte Apr 21 '18 at 20:39
  • "is reachable at least until the assignment is done". So using that after is a pitfall, isn't it? – Gilgamesz Apr 21 '18 at 20:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169515/discussion-between-m-le-rutte-and-gilgamesz). – M. le Rutte Apr 21 '18 at 20:44