sun.nio.ch.DirectBuffer and jdk9/jigsaw

Vitaly Davidovich vitalyd at gmail.com
Thu Feb 23 17:05:36 UTC 2017


On Thu, Feb 23, 2017 at 11:54 AM, Uwe Schindler <uschindler at apache.org>
wrote:

> Hi,
>
> Why do you need the address at all in the Java code? Java code can use the
> official ByteBuffer methods to access the memory you are wrapping. In Java
> 9 that’s optimized very good by Hotspot and should be almost as fast as
> array accesses (we proved that in Apache Lucene - congrats to the Hotspot
> committers). If you need special access modes like volatile access, then
> you can use Java 9's VarHandles. You can get a VarHandle to the backing
> direct buffer using the MethodHandles API.
>
I mentioned this upthread - the base address is used for index calculations
to read/write data using Unsafe directly.  I don't know about Java 9 as
I've not tried it yet, but the generated assembly for using BB methods vs
Unsafe did not favor BB.  There are also various safety checks in
DBB/Buffer internals that won't get optimized away.

Also, my general experience with looking at C2 optimizations has led me to
the conclusion that the optimizations are "unstable" - innocent code
changes, differences in order of how classes are loaded, differences in
what callsites trigger compilation first, and a bunch of other otherwise
benign things can interfere with inlining decisions, which is typically the
reason things go sideways in terms of optimization.

As for MethodHandles and VarHandles, that's one possibility I'm considering
as a way to migrate off using DirectBuffer (although I'd still like to know
if there's any plan to standardize/formalize some notion of a direct
buffer).  However, my understanding is that using MH will still require me
to crack into jdk code (to get access to the DBB and friends) and thus
require addExports.  DirectBuffer is still accessible if using addExports,
but it's a wrinkle I was hoping to iron out, hence what started this email
chain.

>
> Uwe
>
> -----
> Uwe Schindler
> uschindler at apache.org
> ASF Member, Apache Lucene PMC / Committer
> Bremen, Germany
> http://lucene.apache.org/
>
> > -----Original Message-----
> > From: jigsaw-dev [mailto:jigsaw-dev-bounces at openjdk.java.net] On Behalf
> > Of Vitaly Davidovich
> > Sent: Thursday, February 23, 2017 5:30 PM
> > To: Chris Hegarty <chris.hegarty at oracle.com>
> > Cc: jigsaw-dev <jigsaw-dev at openjdk.java.net>
> > Subject: Re: sun.nio.ch.DirectBuffer and jdk9/jigsaw
> >
> > 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