在JNI函数中,当我更改从Java代码传递的Array时,Array不会修改 [英] In JNI function when I change an Array in-place that was passed from Java code the Array doesn't modify

查看:244
本文介绍了在JNI函数中,当我更改从Java代码传递的Array时,Array不会修改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个int数组从Java传递给本机方法. 然后,在JNI函数中,我使用GetIntArrayElements()创建了一个指向int数组的指针,并将其作为* isCopy参数JNI_FALSE传递.我以为这不会创建原始数组的副本,所以我可以在适当的位置修改数组.然后,我使用ReleaseIntArrayElements()并将其作为模式参数JNI_ABORT传递给只是relese缓冲区.但这是行不通的.

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.

来自JNI文档:

  • 模式0:复制内容并释放elems缓冲区
  • 模式JNI_COMMIT:复制内容但不释放elems缓冲区
  • 模式JNI_ABORT:释放缓冲区而无需复制回可能的更改

当我尝试在ReleaseIntArrayElements()中使用模式"0"时,效果很好.但是我不明白为什么原因是我没有创建原始数组的副本,而模式"0"正在复制回内容.

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.

我想JNI总是创建原始数组的副本.但是,随后GetIntArrayElements()中的* isCopy参数失去了意义.那么,这到底发生了什么?

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?

这是我的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);之后,应该检查它是一个out参数.如果返回JNI_FALSE,则不会进行复制.

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.

这是必需的,因为GC可以将元素从一个位置移动到另一位置不可预测地,并且您应始终将更改复制回原始Java数组.因为您永远不知道实际的Java数组的内存位置.

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.

如果您不希望复制该副本,则可能正在寻找该方法的critical版本.这是JNI文档所说的:

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:

这些限制使本地代码>更有可能获得未复制的阵列版本,即使VM>不支持固定

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

这并不意味着只要您持有关键部分,JVM就会禁用垃圾收集,尽管它很可能会这样做.

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.我的:

例如,VM 可以暂时禁用垃圾回收 当本机代码持有指向某个对象的指针时的collection 通过GetPrimitiveArrayCritical

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

这篇关于在JNI函数中,当我更改从Java代码传递的Array时,Array不会修改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆