从内存中释放jni引用

时间:2011-08-01 06:05:28

标签: java-native-interface android-ndk bytearray

我在java中创建一个字节数组,并通过引用jni函数传递它。我在循环中执行此操作,有时会在jni中出现内存不足错误。我想知道java是否在每次迭代时自动释放数组,或者因为它被传递给jni函数,它不会??

JNI代码(bOldArray是我传递给jni作为参数的java字节数组)

len = (*env)->GetArrayLength(env,bOldArray);
char *oldBuff = (char *)calloc(sizeof(char),MAX_SIZE);
jbyte* bytes = (*env)->GetByteArrayElements(env,bOldArray,0);
memcpy(oldBuff,bytes,len);
(*env)->ReleaseByteArrayElements(env,bOldArray,(jbyte *)bytes,0);

2 个答案:

答案 0 :(得分:2)

这里有2个缓冲区,一个来自你的java代码(bOldArray)和你在第2行分配的本地缓冲区(oldbuff)。

实际上,你可能有更多的缓冲区,因为

(*env)->GetArrayLength 

几乎可以肯定地制作了一个不可移动的内存副本(c-pointer-access所需),它将数组保存在你的java代码中并且带有

(*env)->ReleaseByteArrayElements(env,bOldArray,(jbyte *)bytes,0);

将此内存复制回java数组的内存(查看ReleaseByteArrayElements最后一个参数的文档)

但关于你的问题:你也应该释放oldBuff。

free(oldBuff);

否则VM会释放你的java数组的c副本而不是直接释放自我分配的部分(由于对象生命周期和垃圾收集,它可能会稍后发布,但这是不可预测的,因此不可预测内存错误也是不可预测的)

避免java-c-copy机制(加快性能)使用像ByteBuffer这样的共享/静态缓冲区

答案 1 :(得分:0)

如果您正在使用GetByteArrayElements,则必须在完成JNI中的数组后调用ReleaseByteArrayElements,因为JVM将阻止在java中释放此数组,直到您这样做为止。 请发布代码以获得更清晰的想法