JNA 5.2.0 on JDK 11/Windows: crashes when try to pass java.nio.DoubleBuffer allocated off-heap, works on JDK8

76 views
Skip to first unread message

Lev Serebryakov

unread,
Mar 4, 2019, 11:33:01 AM3/4/19
to Java Native Access
Hello!

  I'm trying to benchmark my minimalistic FFTW3 [1] JNA bindinng with new JDK 11 on Windows 10. I've prepared minimal project [2], which wraps only 4 calls of FFTW and several JMH benchmarks.

  I'm using two different FFTW APIs:

  First is «basic» API and it stores pointers to input and output buffers insde C code. It is `JNAAllocated` class. I'm using `DoubleBuffer.allocate()` here to prepare buffers, as per JNA documentation [3].
 
  Second one is «advanced» API, it uses new array for each call, so, I'm using `DoubleBuffer.wrap()`, you could see it in `JNAWrapped` class.

  Both benchmarks work under JDK8. But if I try JDK11, `JNAAllocated` crashes. It is not crash EVERY run, but one time out of 2-3 it crashes with access violation.

  `JNAWrapped` works 100% of time.

  I'm not sure, is it bug in my bindings (and absence of problems on JDK8 is pure luck), or it is bug in JNA + JDK11 combination, and if it is, which part has real bug!

  Should I report is as JNA bug? Maybe, it is trivial bug in my wrapper?


--
// Lev Serebryakov

Neil C Smith

unread,
Mar 4, 2019, 12:35:41 PM3/4/19
to jna-users
On Mon, 4 Mar 2019, 16:33 Lev Serebryakov, <blac...@gmail.com> wrote:
I'm using `DoubleBuffer.allocate()` here to prepare buffers, as per JNA documentation [3].

DoubleBuffer.allocate() is array backed and not off-heap. That might be the issue? 

Best wishes, 

Neil

Lev Serebryakov

unread,
Mar 4, 2019, 12:42:19 PM3/4/19
to jna-...@googlegroups.com
On Mon, Mar 4, 2019 at 8:35 PM 'Neil C Smith' via Java Native Access
<jna-...@googlegroups.com> wrote:

>> I'm using `DoubleBuffer.allocate()` here to prepare buffers, as per JNA documentation [3].
>
> DoubleBuffer.allocate() is array backed and not off-heap. That might be the issue?
Yep. I'm idiot. Sorry for noise on list.


--
// Black Lion AKA Lev Serebryakov

Matthias Bläsing

unread,
Mar 4, 2019, 1:01:16 PM3/4/19
to jna-...@googlegroups.com
Hi,

Am Montag, den 04.03.2019, 20:42 +0300 schrieb Lev Serebryakov:
> On Mon, Mar 4, 2019 at 8:35 PM 'Neil C Smith' via Java Native Access
> <jna-...@googlegroups.com> wrote:
>
> > > I'm using `DoubleBuffer.allocate()` here to prepare buffers, as
> > > per JNA documentation [3].
> >
> > DoubleBuffer.allocate() is array backed and not off-heap. That
> > might be the issue?
> Yep. I'm idiot. Sorry for noise on list.

Neils thought sounds right. JNA can handle the non-direct buffer case
for pure Java -> C transitions, if the buffer is only used for the
duration of the call itself. This comes with a speed penalty though, as
the backing array is accessed and in most cases this be a copy.

However, there is another problem: The buffer
jna.JNAAllocated.BenchState.i becomes eligible for garbadge collection
directly after line line 54, before the
FFTW3Library.INSTANCE.fftw_execute(state.p) call, as it is not accessed
from java code anymore. The fftw_plan is not enough to strongly
reference the input array, as the GC can't "look" into it.

Adding a reachability fence should protect you from that:

Reference.reachabilityFence(state.i);

HTH

Matthias

Lev Serebryakov

unread,
Mar 4, 2019, 1:04:52 PM3/4/19
to jna-...@googlegroups.com
> However, there is another problem: The buffer
> jna.JNAAllocated.BenchState.i becomes eligible for garbadge collection
> directly after line line 54, before the
> FFTW3Library.INSTANCE.fftw_execute(state.p) call, as it is not accessed
> from java code anymore. The fftw_plan is not enough to strongly
> reference the input array, as the GC can't "look" into it.
As far as I understand, `BenchState` insance will be referenced by
JMH framework for whole benchmark iteration (each iteration is
multiple calls to `@Benchmark`-marked function), so it will be
reachable till benchmark ends without problems via BenchState
instance.
Reply all
Reply to author
Forward
0 new messages