3

I have to mix c++ code with java. The java part allocates a java.nio.ByteBuffer and the c++ part gets it's address via env->GetDirectBufferAddress(buffer) as a jbyte* and fills in data.

ByteOrder is ok. Data can be retrieved in java via buffer.get() .getLong() etc.

However, the method buffer.array() fails and hasArray() returns false. If I use buffer.allocate(size) instead of .allocateDirect(size) the method array() works well, but my c++ code gets a DirectBufferAddress of NULL and fails.

My question: how can I best combine both worlds, with least copying of data? Or, how to easiest fill a java byte[] with native c++ data ?

datafiddler
  • 1,755
  • 3
  • 17
  • 30

1 Answers1

9

ByteBuffer class is indeed confusing. It is actually a wrapper around one of two entirely different classes: DirectByteBuffer and ArrayByteBuffer. Why this happened, is a question for historians.

As far as the programmers are concerned, we must use DirectByteBuffer to achieve fastest, no-copy access from C, but access to DirectByteBuffer from Java may be quite slow, and it lacks the flexibility of byte[]. The array-based ByteBuffer has no advantage for C libraries, but it may be much more efficient on the Java side.

On the other hand, JNI does provide access to primitive arrays, including byte[]. In many cases, such access does not involve copy, especially if you use GetPrimitiveArrayCritical(). Well, there is no guarantee. But If you use a modern optimized JVM on modern hardware with abundant physical RAM and almost unlimited virtual RAM, your chances to have efficient access from both C/C++ and Java are very high.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 2
    Good hint, to watch out beyond the scope of ByteBuffer. Hesitating to touch the existing c++ code and "research" GetPrimitiveArrayCritical() is no excuse ;) – datafiddler May 26 '16 at 16:25