Suppose that I have a C data-structure containing many data fields (>15):
struct MyData
{
int x;
float y;
...
}
In Java, I can store a pointer to a MyData as a long, and access members of the C data structure through JNI calls:
long mydata_p = MyDataJNI.alloc();
int x = MyDataJNI.getX( mydata_p );
float y = MyDataJNI.getY( mydata_p );
...
However, the calls to these functions are shockingly expensive (10x-100x the cost of an equivalent C function call). This is true even if the implementation getX, getY, … is as simple as:
return ((MyData*)())->x
Q1: Why are JNI calls so expensive? What else is going on other than a call to a function pointer? (For reference, I’m looking at JNI calls in Android.)
Q2: What is the fastest what to make all of the elements of my C structure available at the Java layer?
You want to move all of the data with a single JNI call. You can either copy it into a primitive byte array (and then extract Java primitives from that using some combination of ByteArrayOutputStream and DataOutputStream), or use a direct NIO ByteBuffer (ByteBuffer.allocateDirect), which makes more sense if you need to move data back and forth. The direct ByteBuffer is specifically designed and optimized for sharing memory between the VM and native code.