Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I've found plenty of tutorials / questions on Stackoverflow that deal with copying char arrays from C/JNI side into something like a byte[] in Java, but not the other way around.

I am using a native C library which expects a byte array. I simply want to get data from a byte[] in java, into preferably an unsigned char[] in C.

Long story short: What is the best way of copying data from a jBytearray in JNI? Is there any way to detect it's size?

The best way to copy a Java byte[] to a native char* is to use the GetByteArrayRegion call. It does exactly what you want: copies all or part of an array of bytes into a native buffer.

Using GetByteArrayElements / ReleaseByteArrayElements requires two calls instead of one, and depending upon the VM's implementation will either pin the byte[] in memory to prevent the GC from moving it, or cause a copy so the GC can freely move the original without disrupting the native code. (This also means that JNI_ABORT will either "undo" changes or leave them intact, depending on whether the buffer was pinned or copied.)

(See also the "Region Calls" section of the JNI Tips document.)

The GetArrayLength call can be used to determine the size of the byte[] .

Here's a working example I just lifted from my AS/400 JNI library to resolve a native user-queue pointer to test the queue's existence - it copies the queue library and name from a Java byte array (already translated to job's CCSID) into native code and uses it. Take note of the release function calls; these can be changed to copy the native array contents back into the Java byte arrays to move data the other way:

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; }                                                                                           
                Already had this working since 3 weeks ago (mangler.org/trac/browser/branches/android/project/jni/ventrilo/…), but it is the right answer nonetheless. Upvote & accept.
– Daniel Sloof
                Mar 10, 2010 at 14:11
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.