In JNI function when I change an Array in-place that was passed from Java code the Array doesn't modify

Igor :

I'm passing an int array from Java to native method. Then within JNI function I created a pointer to int array with GetIntArrayElements() and pass as *isCopy argument JNI_FALSE. I supposed that this will not create a copy of the original array and I could modify array in place. Then I use ReleaseIntArrayElements() and pass as mode argument JNI_ABORT to just relese buffer. But that didn't work.

From JNI documentation:

  • mode 0: copy back the content and free the elems buffer
  • mode JNI_COMMIT: copy back the content but do not free the elems buffer
  • mode JNI_ABORT: free the buffer without copying back the possible changes

That when I tried to use mode "0" in ReleaseIntArrayElements() that worked perfectly. But I don't understand why cause I didn't create a copy of the original array and mode "0" is copying back the content.

I suppose that JNI always create a copy of the original array. But then *isCopy argument in GetIntArrayElements() lose its sense. So what really happening with this?

THIS IS MY JNI FUCNTION

extern "C" JNIEXPORT jdouble JNICALL
Java_my_own_package_MainActivity_myFunction(
    JNIEnv *env,
    jobject /* this */, jintArray tbl) {
    jint *tblptr = env->GetIntArrayElements(tbl, JNI_FALSE);
    tblptr[0] = 0; //in-place change
    env->ReleaseIntArrayElements(tb1, tblptr, JNI_ABORT);
    return 0;
}
Some Name :

You misused the jboolean *isCopy. It is an out parameter you should examine after the actual call to env->GetIntArrayElements(tbl, isCopy);. If it returns JNI_FALSE then the copy is not made.

This is necessary since GC can move elements from one location to another unpredictably and you should always copy the changes back to the original java array. Because you never know the memory location of the actual java array.

If you dont want the copy is made you are probably looking for a critical version of the method. Here is what the JNI docs says:

These restrictions make it more likely that the native code > will obtain an uncopied version of the array, even if the VM > does not support pinning

This does not mean that JVM will disable garbage collection as long as you are holding a critical section although it is likely to do so.

Emp. Mine:

For example, a VM may temporarily disable garbage collection when the native code is holding a pointer to an array obtained via GetPrimitiveArrayCritical

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=112529&siteId=1