Search code examples
javac++arraysjava-native-interface

How to get just an ordinary 1D array instead of a 2D array via JNI?


So I have no experience with JNI, however I need to change a small part of the code I am given.

In my c++ code, I have this method defined (which java side code calls):

JNIEXPORT void JNICALL sumTraces
  (JNIEnv* env, jclass caller, jobjectArray jPrestackArrays, jint count) {

The jPrestackArrays jobjectArray is a 2D float array [][] passed in by the java side. After the above code is:

float** prestack2D = (float**)malloc(nTracesIn * sizeof(float*));
for (int j = 0; j < count; j++) {
   jfloatArray floatArrayJ = (jfloatArray)env->GetObjectArrayElement(jPrestackArrays, j);
   prestack2D[j] = (float*)env->GetPrimitiveArrayCritical(floatArrayJ, &isCopy);
}

And the code ends with:

  for (int j = 0; j < count; j++) {
    jfloatArray floatArrayJ = (jfloatArray)env->GetObjectArrayElement(jprestackTraces, j);
    env->ReleasePrimitiveArrayCritical(floatArrayJ, prestack2D[j], JNI_ABORT);
  }

And so that gives me a 2D array that I can use in the c++ code.

However I need to change this code to instead just make it a normal 1D float array [] that java passes in (such that float** prestack2D becomes float* prestack1D).

What exactly do I change in order to just get a normal float array? I tried GetObjectField and GetFloatArrayElements with no luck. I presume that this is a really answer easy question however like I said I have no experience with JNI and I am exhausted right now, and JNI's documentation is not as good as what I am used to.


Solution

  • So, your Java method will be

    static native void sumTraces(float[], int);
    

    and its C++ side

    JNIEXPORT void JNICALL sumTraces
        (JNIEnv* env, jclass caller, jfloatArray jPrestackArray, jint count);
    

    Now, you can use

    float* prestack1D = (float*)env->GetPrimitiveArrayCritical(jPrestackArray, &isCopy);
    

    Don't forget to release:

    env->ReleasePrimitiveArrayCritical(jPrestackArray, prestack1D, JNI_ABORT);
    

    Note that you should always try release array locked with GetPrimitiveArrayCritical() as quickly as possible. The original code looks dangerous because if it locks many arrays, and does heavy processing, the Java VM may get starved.