sun.nio.ch.DirectBuffer and jdk9/jigsaw

Vitaly Davidovich vitalyd at gmail.com
Thu Feb 23 16:29:57 UTC 2017


On Thu, Feb 23, 2017 at 11:10 AM, Chris Hegarty <chris.hegarty at oracle.com>
wrote:

>
> > On 23 Feb 2017, at 11:30, Vitaly Davidovich <vitalyd at gmail.com> wrote:
> >> ...
> > The buffers are reused by having them point to different native memory
> > block addresses; those blocks are managed by native code.  As mentioned,
> > the ByteBuffer (DirectByteBuffer concretely) is used as the Java level
> > interface/view of native memory, allowing Java and native code to
> > communicate.
>
> So a DBB, under your code, may report a different address at some time
> in the future, to that of what it currently reports?

Correct.

> I was not aware of this
> usecase. Is any similar code available on the web, or elsewhere, so we
> could try to determine why this is being done?
>
Unfortunately it's not open source code, and I don't immediately know of
anything similar on the web (or otherwise).  However, the gist is the
following:
1) Allocate a 0-size DBB (i.e. ByteBuffer.allocateDirect(0)).  This gives
you a Java "handle", if you will, to some native memory.  But, since this
DBB will be attached/reattached to different memory dynamically, there's no
need for an actual allocation.
2) Native code wants to expose a segment of memory to Java.  In JNI, it
sets the address and capacity of this DBB to the pointer where the native
memory segment starts, and to the capacity (it knows how big the native
segment is).  Java code asks for this DBB to be "attached" to, say, some
sort of message, and the JNI/native code perform these functions.
3) Java gets the attached DBB back, and can then use its API
(getXXX/setXXX) to read/write that native block.  Once the operation
completes, the DBB is recycled for reuse (i.e. can be attached to a
different native segment again).

Obviously, we can use
http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetDirectBufferAddress
to get the address and then expose that via a JNI helper - in fact, that's
what was done before.  But, there's a JNI call penalty here for what is
otherwise a memory read.  DirectBuffer::address() solves that nicely, and
also plays well with the C2 JIT (as mentioned) because the callsites where
this is used only see DBB, and then the whole invokeinterface call is
devirtualized and inlined into a quick type check and Java field read - the
performance of this is, as you can imagine, significantly better than the
JNI approach.

If you think of what a DBB really is, it's pretty much what it's name
suggests - it's an API to read/write to native memory, rather than Java
heap memory (i.e. HeapByteBuffer).  But, there's no reason the native
memory backing the DBB has to also be allocated via Unsafe itself, although
that's the more common scenario.

On the Java side, consumers of this have a common and conventional API over
a byte buffer, i.e. ByteBuffer, which can optionally be used in the manner
above (obviously callers will need to know what mode they're using).


> -Chris.
>
>


More information about the jigsaw-dev mailing list