18

我在 Stackoverflow 上找到了很多教程/问题,这些教程/问题涉及将 char 数组从 C/JNI 端复制到 Java 中的 byte[] 之类的东西中,但反之则不然。

我正在使用一个需要字节数组的本机 C 库。我只是想从 java 中的 byte[] 获取数据,最好是 C 中的 unsigned char[]。

长话短说:从 JNI 中的 jBytearray 复制数据的最佳方法是什么?有没有办法检测它的大小?

4

2 回答 2

18

将 Java byte[] 复制到本机的最佳方法char*是使用GetByteArrayRegion调用。它完全符合您的要求:将全部或部分字节数组复制到本机缓冲区中。

使用GetByteArrayElements/ReleaseByteArrayElements需要两次调用而不是一次调用,并且取决于 VM 的实现,要么将 byte[] 固定在内存中以防止 GC 移动它,要么导致复制以便 GC 可以自由移动原始代码而不会破坏本机代码。(这也意味着JNI_ABORT将“撤消”更改或保持不变,具体取决于缓冲区是固定还是复制。)

(另请参阅JNI Tips文档的“区域调用”部分。)

GetArrayLength调用可用于确定byte[].

于 2010-03-19T20:49:40.627 回答
17

这是我刚刚从我的 AS/400 JNI 库中提取的一个工作示例,用于解析本机用户队列指针以测试队列的存在——它将队列库和名称从 Java 字节数组(已转换为作业的 CCSID)复制到本机代码并使用它。注意释放函数调用;可以更改这些以将本机数组内容复制回 Java 字节数组,以另一种方式移动数据:

JNIEXPORT jboolean JNICALL Java_com_mycompany_jni400_UserQueue_jniResolve(JNIEnv *jep,jobject thsObj,                
jbyteArray queueLibrary,jbyteArray queueName) {                                                                             
    jbyte            *lib,*nam;                                                                                             
    bool             rtn;                                                                                                   

    thsObj=thsObj;                                                                                                          
    lib=(*jep)->GetByteArrayElements(jep,queueLibrary,0);                                                                   
    nam=(*jep)->GetByteArrayElements(jep,queueName,0);                                                                      
    rtn=(usrq_resolve((byte*)lib,(byte*)nam)!=NULL);                                                                        
    (*jep)->ReleaseByteArrayElements(jep,queueLibrary,lib,JNI_ABORT); /* abort to not copy back contents */                 
    (*jep)->ReleaseByteArrayElements(jep,queueName   ,nam,JNI_ABORT); /* abort to not copy back contents */                 
    if(rtn) { return JNI_TRUE;  }                                                                                           
    else    { return JNI_FALSE; }                                                                                           
    }                                                                                                                       
于 2010-03-10T08:09:58.617 回答