我传递从Java的int数组给本地方法。然后JNI函数内我创建了一个指针到int与GetIntArrayElements阵列(),并通过作为完成后将* isCopy参数JNI_FALSE。我认为,这不会创建原始数组的一个副本,我可以代替修改阵列。然后我使用ReleaseIntArrayElements(),并通过作为模式参数JNI_ABORT只是relese缓冲器。但是,这并不能正常工作。
从JNI文档:
当我试图使用ReleaseIntArrayElements,完美的工作模式“0”()。但我不明白为什么,因为我没有创建原始阵列和模式的副本“0”被复制回内容。
我想,JNI总是创建原始数组的一个副本。但随后在* GetIntArrayElements isCopy参数()失去其意义。所以,真正有这样的情况?
这是我的JNI函数
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;
}
你滥用了jboolean *isCopy
。这是实际调用env->GetIntArrayElements(tbl, isCopy);
后,你应该检查的输出参数。如果返回JNI_FALSE
那么,副本将不会作出。
这是必要的,因为GC可以从一个位置不可预测移动元素到另一个,你应该更改回总是复制到原来的Java数组。因为你永远不知道实际的Java数组的存储位置。
如果你不想创建副本你可能寻找方法的critical
版本。下面是JNI文档所说的话:
这些限制使得它更可能是本地代码>将获得阵列的未复制版本,即使虚拟机>不支持钉住
这并不意味着,JVM将只要禁用垃圾收集你拿着一个关键部分,虽然它很可能这样做。
EMP。矿:
例如,VM可以暂时禁用在本机代码被保持经由
GetPrimitiveArrayCritical
获得的指针数组的垃圾收集
你似乎误解了isCopy
的GetIntArrayElements
参数的目的。它不是一个输入参数告诉GetIntArrayElements
是否应该给你的阵列数据的副本;它是GetIntArrayElements
可以用它来告诉你它是否创造了一个副本的输出参数。
从文档:
如果isCopy非空,然后完成后将* isCopy设置为JNI_TRUE,如果一份拷贝;或者它被设置,如果没有副本作出JNI_FALSE。
所以,如果你传递一个非空jboolean*
您可以稍后在检查该值。如果你通过NULL
你没有得到这个信息。例如,如果你只打算从数据读取,然后知道它是否是一个副本,可能不是因为你可能只是要释放的元素时使用JNI_ABORT
很有趣。