How to read a bytearray in JNI?

大城市里の小女人 提交于 2019-12-22 07:24:12

问题


Is it possible to just reference a entire bytearray in JNI but not invoking any copy ?

In native C code, I have a bytearray passing from Java, and I just want to compare some data to this bytearray so I do not want to do any memory copy. Is it possible ?

I know I could get the pointer of a bytearray in native by using GetPrimitiveArrayCritical something like that

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;
}

As you could see, because I might change the data in the jbIn, I should use GetPrimitiveArrayCritical to get its pointer and release it later.

However, if I just want to READ the bytearray jbBase, how could I get the pointer of the jbBase but not using GetPrimitiveArrayCritical ?

Any suggestion would be appreciated. Thanks a lot.


回答1:


I use the following to read byte arrays...

jbyte *b = (jbyte *)env->GetByteArrayElements(jbBase, NULL);
// read bytes in *b here
...
// release it
env->ReleaseByteArrayElements(jbBase, b, 0 );

You still need to release it as that stops the Garbage collector getting rid of it potentially while you are still using it.




回答2:


GetByteArrayElements method can not guarantee that your program use reference or copy. JNI return isCopy flag for state it copied object or pinned it(pin means reference). If you dont want to copy it never, you havent to use GetArrayElements methods, because it always returns copy(JVM decides copy or not and probably copy prefered because copy eases burden of Garbage Collector). I tried it and I saw that my ram increased when sent a big array. You can also see that at below link:

IBM copy and pin (look at copy and pin subject from tree view)

As document says,GetPrimitiveArrayCritical returns the direct heap address of a Java array, disabling garbage collection until the corresponding ReleasePrimitiveArrayCritical is called. So you must use that GetPrimitiveArrayCritical, if you dont want to copy(u need that when you have a big array). If we look at your code, you can get array one by one as below(I assumed you sent int array as a jobject to JNI function):

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);

Important Note: You cannot GetArrayLength after GetPrimitiveArrayCritical because JNI doesn't permit program to call any JNI function for same object between get critical and release methods.



来源:https://stackoverflow.com/questions/6728616/how-to-read-a-bytearray-in-jni

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!