Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI direct buffers. Who is responsible for native buffer freeing?

Assume in one hand we have a direct byte buffer created with env->NewDirectByteBuffer(). In other hand we have similar direct buffer, but created with ByteBuffer.allocateDirect(). Obviously both these objects should be managed by JVM in the same manner, including management of the backing native buffer, which in first case was provided by user, and in second case was allocated by JVM from native heap.

Of course JVM must free backing buffer during GC'ing of the second object (instantiated with ByteBuffer.allocateDirect()).

And my question: Will JVM try to deallocate buffer during GC'ing of the first object (instantiated with env->NewDirectByteBuffer()) ?

P.S. I've not found clear answer neither at JNI docs neither at SO. The most helpful info was here http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html :

Direct ByteBuffer objects clean up their native buffers automatically but can only do so as part of Java heap GC — so they do not automatically respond to pressure on the native heap.

So it seems like JVM will free backing buffers during GC pass, but there is no any mentions about deallocator. Is it plain free() or something else.

like image 653
Sergio Avatar asked Feb 12 '16 13:02

Sergio


1 Answers

When you are calling the JNI NewDirectByteBuffer(void* address, jlong capacity) a DirectByteBuffer object will be created, using the following constructor:

private DirectByteBuffer(long addr, int cap) {
    super(-1, 0, cap, cap);
    address = addr;
    cleaner = null;
    att = null;
}

Notice that the cleaner property is null.

If you create a DirectByteBuffer via ByteBuffer.allocateDirect() the cleaner property is set (see source code of DirectByteBuffer).

Now the cleaner is a utility object whose clean method is run when the buffer is garbage collected (see this explanation for details).

For the buffer constructed via ByteBuffer.allocateDirect() the cleaner deallocates the direct memory.

For the JNI constructed buffer no such operation is done. You need to free this memory yourself.

like image 118
wero Avatar answered Oct 13 '22 00:10

wero