天天看點

Android NDK學習筆記6-JNI對引用資料類型的操作

字元串操作

    JNI把Java字元串當成引用類型來處理,JNI提供了java字元串與C字元串之間互相轉換的必要函數。因為java字元串對象是不可變的,是以JNI不提供任何修改現有的java字元串内容的函數。

● 建立字元串

    可以在原生代碼中用NewString函數建構Unicode編碼格式的字元串執行個體,用NewStringUTF函數建構UTF-8編碼格式的字元串執行個體。

    例如:下面的函數以一個C字元串為參數,并傳回一個Java字元串引用類型jstring值。

jstring javastring
javastring = (*env)->NewStringUTF(env, "I LOVE YOU UU!");
           

注意,在記憶體溢出的情況下,NewString函數将傳回NULL以通知原生代碼虛拟機中有異常抛出。

● 把java字元串轉換成C字元串

    為了在原生代碼中使用java字元串,需要先将java字元串轉換成C字元串,我們使用GetStringChars函數可以将Unicode格式的java字元串轉換成C字元串,使用GetStringUTFChars函數可以将UTF-8格式的Java字元串轉換成C字元串。這些函數的第三個參數均為可選參數,該可選參數名是isCopy,它讓調用者确定傳回的C字元串位址指向副本還是指向堆中的固定對象。例如:

const jbyte* str;
jboolean isCopy;

str = (*env)->GetStringUTFChars(env, javaString,&isCopy);
if( != str){
    printf("java String: %s",str);
    if(JNI_TRUE == isCopy){
        printf("C String is a copy of the java String");
    }else{
        printf("C String points to actual String");
    }
}
           

● 釋放字元串

    通過JNI GetStringChars 函數GetStringUTFChars函數獲得的C字元串在原生代碼中使用完成之後需要正确的釋放,否則将會引起記憶體洩漏。通常我們使用ReleaseStringChars函數釋放Unicode格式的字元串,使用ReleaseUTFStringChars函數釋放UTF-8格式的字元串.

(*env)->ReleaseUTFStringChars(env,javaString,str);
           

數組操作

    JNI把java數組當成引用類型來處理,JNI提供必要的函數通路和處理Java數組。

● 建立數組

    用NewArray函數在原生代碼中建立數組執行個體,其中可以是Int、Char和Boolean等。例如:

jintArray javaArray;
javaArray = (*env)->NewIntArray(env,);
if( != javaArray){
/*數組使用……*/
}
           

    注意,在記憶體溢出的情況下,NewArray函數将傳回NULL以通知原生代碼虛拟機中有異常抛出。

● 通路數組元素

JNI提供兩種通路java數組元素的方法,可以将數組的代碼指派成C數組或者讓JNI提供直接執行數組元素的指針。

● 對副本的操作

    GetArrayRegion函數将給定的基本Java數組指派到給對你給的C數組中,例如:

jint nativeArray[];
(*evn)->GetIntArrayRegion(env,javaArray,,,nativeArray);
           

    原生代碼可以像使用普通的C數組一樣使用和修改數組元素。當原生代碼想将所做的修改送出給java數組時,可以使用SetArrayRegion函數将C數組複制回java數組中。例如:

(*env)->SetIntArrayRegion(env,javaArray,,,nativeArray);
           

注意:當數組很大時,對數組做複制操作會引起性能問題。

● 對直接指針的操作

    原生代碼可以使用GetArrayElements函數擷取執行數組元素的直接指針。例如:

jint nativeDirectArray;
jboolean isCopy;

nativeDirectArray = (*env)->GetIntArrayElements(env,javaArray,&isCopy);
           

    其中,第三個&isCopy參數為可選參數,讓調用者确定傳回的C字元串位址指向副本還是指向堆中的固定對象。

    因為可以像普通的C數組一樣通路和處理數組元素,是以JNI沒提供通路和處理數組元素的方法,JNI要求原生代碼用完這些指針後立刻釋放,否則會出現記憶體溢出。可以使用JNI提供的ReleaseArrayElements函數釋放GetArrayElements傳回的C數組。例如:

(*env)->ReleaseIntArrayRegion(env,javaArray,nativeDirectArray,);
           

    其中第四個參數是釋放模式。

    釋放模式動作0将内容複制回來并釋放原生數組JNI_COMMIT将内容複制回來但是不釋放原生數組,一般用于周期性的更新一個java數組JNI_ABORT釋放原生數組但不用将内容複制回來

Android NDK學習筆記6-JNI對引用資料類型的操作

繼續閱讀