如何在 JNI 中读取字节数组?

发布于 2024-11-24 14:34:32 字数 907 浏览 2 评论 0原文

是否可以在 JNI 中引用整个字节数组而不调用任何副本?

在本机 C 代码中,我有一个从 Java 传递的字节数组,我只想将一些数据与该字节数组进行比较,因此我不想进行任何内存复制。是否可以 ?

我知道我可以通过使用 GetPrimitiveArrayCritical 来获取本机中字节数组的指针,如

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 来获取其指针并稍后释放它。

但是,如果我只想读取字节数组 jbBase,如何获取 jbBase 的指针而不使用 GetPrimitiveArrayCritical ?

任何建议将不胜感激。多谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜血缘 2024-12-01 14:34:32

我使用以下内容来读取字节数组...

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

您仍然需要释放它,因为这会阻止垃圾收集器在您仍在使用它时可能删除它。

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.

三生路 2024-12-01 14:34:32

GetByteArrayElements方法不能保证您的程序使用引用或复制。 JNI 返回 isCopy 标志来表示它复制了对象或固定它的状态(pin 表示引用)。如果您不想永远复制它,则不必使用 GetArrayElements 方法,因为它总是返回副本(JVM 决定是否复制,并且可能首选复制,因为复制减轻了垃圾收集器的负担)。我尝试了一下,发现发送大数组时我的内存增加了。您还可以在以下链接中看到:

IBM 复制和固定(从树视图中查看复制和固定主题)

作为文档说,GetPrimitiveArrayCritical 返回 Java 数组的直接堆地址,禁用垃圾收集,直到调用相应的 ReleasePrimitiveArrayCritical。因此,如果您不想复制,则必须使用 GetPrimitiveArrayCritical(当您有一个大数组时,您需要它)。如果我们查看您的代码,您可以如下所示一一获取数组(我假设您将 int 数组作为 jobobject 发送到 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 不允许程序调用任何 JNI在获取关键方法和释放方法之间为同一对象提供函数。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文