Reputation: 4021
Since I want to know whether it is worth it to use JNI
to improve the performance of my application, I wanted to know what the complexity of GetIntArrayElements
is. Does it always allocate a new primitive array in C
and copy all the elements from the original Java
array, or it somehow manages to pass a pointer?
I want to find out if it's worth it to use JNI
for algorithms that are linear, e.g. pointwise multiplication of two vectors. In case GetIntArrayElements
is linear, I guess the potential performance boost from using C/C++
would be lost if we need to copy the vectors first.
Upvotes: 1
Views: 517
Reputation: 33875
GetIntArrayElements
has an optional by-reference parameter called isCopy
. When the VM makes a copy of the data for you to use, this parameter will be set to JNI_TRUE
. The idea is that different VM implementations might have different memory representations of an array, also one that is not compatible with the memory layout that C expects.
Usually the fastest way of sharing memory between Java and native code is by using direct ByteBuffer
s (ones that are created with allocateDirect
). These buffers use an underlying block of memory that is directly usable from C/C++.
In Java you create a buffer and fill it with some data:
public static void main(String[] args) {
byte[] ba = "Hello Wolrd!".getBytes(StandardCharsets.US_ASCII);
ByteBuffer bb = ByteBuffer.allocateDirect(ba.length + 1); // for terminator
bb.put(ba);
callCPP(bb);
}
private static native void callCPP(ByteBuffer bytes);
And then from C/C++ you can get the address of the underlying block of bytes with GetDirectBufferAddress
(this is in C++):
JNIEXPORT void JNICALL Java_Main_callCPP(JNIEnv *env, jclass, jobject buff) {
const char* str = (char*) env->GetDirectBufferAddress(buff);
printf(str); // Hello World!
}
The downside of using a ByteBuffer
is that there is no data abstraction, like a class' field has a specific type, a position in the byte buffer does not.
Upvotes: 1