字元串操作
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釋放原生數組但不用将内容複制回來