是否可以在JNI中引用整个bytearray但不调用任何副本?
在本机C代码中,我有一个从Java传递的bytearray,我只是想将一些数据与这个bytearray进行比较,所以我不想做任何内存复制。有可能吗?
我知道我可以通过使用类似的GetPrimitiveArrayCritical来获取本地的bytearray指针
JNIEXPORT jbyteArray JNICALL Java_nfore_android_bt_pro_nfhfp_dsp
(JNIEnv *env, jobject jobj, jbyteArray jbIn, jbyteArray jbBase){
jbyte *bufferIn;
jbyte *bufferBase;
bufferIn = (*env)->GetPrimitiveArrayCritical(env, jbIn, NULL);
LOGD("Begin of dsp()");
LOGD("In dsp() Before Comparing...");
// Compare bufferIn with bufferBase here...
LOGD("In dsp() After Comparing...");
LOGD("End of dsp()");
(*env)->ReleasePrimitiveArrayCritical(env, jbIn, bufferIn, 0);
return jbIn;
}
正如您所看到的,因为我可能会更改jbIn中的数据,所以我应该使用GetPrimitiveArrayCritical获取其指针并稍后释放它。
但是,如果我只想读取bytearray jbBase,我怎么能得到jbBase的指针但不能使用GetPrimitiveArrayCritical?
任何建议都将不胜感激。非常感谢。
答案 0 :(得分:9)
我使用以下内容来读取字节数组......
jbyte *b = (jbyte *)env->GetByteArrayElements(jbBase, NULL);
// read bytes in *b here
...
// release it
env->ReleaseByteArrayElements(jbBase, b, 0 );
你还需要释放它,因为它会阻止垃圾收集器在你还在使用它的时候摆脱它。
答案 1 :(得分:6)
GetByteArrayElements方法无法保证您的程序使用引用或复制。 JNI返回isCopy标志,表示它复制了对象或固定它(pin表示引用)。如果你不想永远复制它,你不必使用GetArrayElements方法,因为它总是返回副本(JVM决定是否复制,可能是复制首选,因为复制减轻了垃圾收集器的负担)。我试过了,看到我的ram在发送一个大阵列时增加了。您还可以在以下链接中看到:
IBM copy and pin(从树状视图查看副本和图钉主题)
正如文档所述,GetPrimitiveArrayCritical返回Java数组的直接堆地址,禁用垃圾收集,直到调用相应的ReleasePrimitiveArrayCritical。所以你必须使用GetPrimitiveArrayCritical,如果你不想复制(当你有一个大数组时需要它)。如果我们查看你的代码,你可以按如下所示逐个获取数组(我假设你将int数组作为一个jobject发送到JNI函数):
length = (*env)->GetArrayLength(jbIn);
bufferIn = (*env)->GetPrimitiveArrayCritical(env, jbIn, NULL);
for(int i=0; i<length; i++)
printf("Value of jbIn[%d]: %d", i, bufferIn[i]);
(*env)->ReleasePrimitiveArrayCritical(env, jbIn, bufferIn, 0);
重要说明:GetPrimitiveArrayCritical之后不能使用GetArrayLength,因为JNI不允许程序在get critical和release方法之间为同一个对象调用任何JNI函数。