JNI 字符串
- 創(chuàng)建 jsting 字符串(C、C++ 的字符串返回給 java)
jstring NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);
jstring NewStringUTF(JNIEnv *env, const char *bytes);
這個(gè)新創(chuàng)建的字符串會(huì)自動(dòng)轉(zhuǎn)換成Java支持的Unicode編碼。如果JVM不能為構(gòu)造java.lang.String分配足夠的內(nèi)存,NewStringUTF會(huì)拋出一個(gè)OutOfMemoryError異常,并返回NULL
- 獲取 jsting 長度(由于UTF-8編碼的字符串以'\0'結(jié)尾,而Unicode字符串不是)
jsize GetStringLength(JNIEnv *env, jstring string);
jsize GetStringUTFLength(JNIEnv *env, jstring string);
- 從 jstring 中獲取 char * (獲取 java 傳遞給 C、C++ 的字符串)
const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
const char* GetStringUTFChars(jstring string, jboolean* isCopy)
isCopy:取值JNI_TRUE和JNI_FALSE,如果值為JNI_TRUE,表示返回JVM內(nèi)部源字符串的一份拷貝,并為新產(chǎn)生的字符串分配內(nèi)存空間。如果值為JNI_FALSE,表示返回JVM內(nèi)部源字符串的指針,意味著可以通過指針修改源字符串的內(nèi)容,不推薦這么做,因?yàn)檫@樣做就打破了Java字符串不能修改的規(guī)定。但我們在開發(fā)當(dāng)中,并不關(guān)心這個(gè)值是多少,通常情況下這個(gè)參數(shù)填nullptr即可
const char* s = env->GetStringUTFChars(sFromJava, nullptr);
不管有沒有復(fù)制一份,使用完了都需要 release。(從 java 中 get 到的類和對象都需要 release)
- 從字符串中的指定位置復(fù)制指定長度的字符到字符數(shù)組中
void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
GetStringUTFRegion這個(gè)函數(shù)會(huì)做越界檢查,如果檢查發(fā)現(xiàn)越界了,會(huì)拋出StringIndexOutOfBoundsException異常,這個(gè)方法與GetStringUTFChars比較相似,不同的是,GetStringUTFRegion內(nèi)部不分配內(nèi)存,不會(huì)拋出內(nèi)存溢出異常。
GetStringUTFRegion和GetStringRegion這兩個(gè)函數(shù)由于內(nèi)部沒有分配內(nèi)存,所以JNI沒有提供ReleaseStringUTFRegion和ReleaseStringRegion這樣的函數(shù)。
字符串總結(jié)
- 對于小字符串來說,GetStringRegion和GetStringUTFRegion這兩對函數(shù)是最佳選擇,因?yàn)榫彌_區(qū)可以被編譯器提前分配,而且永遠(yuǎn)不會(huì)產(chǎn)生內(nèi)存溢出的異常。當(dāng)你需要處理一個(gè)字符串的一部分時(shí),使用這對函數(shù)也是不錯(cuò)。因?yàn)樗鼈兲峁┝艘粋€(gè)開始索引和子字符串的長度值。另外,復(fù)制少量字符串的消耗 也是非常小的。
- 使用GetStringCritical和ReleaseStringCritical這對函數(shù)時(shí),必須非常小心。一定要確保在持有一個(gè)由 GetStringCritical 獲取到的指針時(shí),本地代碼不會(huì)在 JVM 內(nèi)部分配新對象,或者做任何其它可能導(dǎo)致系統(tǒng)死鎖的阻塞性調(diào)用
- 獲取Unicode字符串和長度,使用GetStringChars和GetStringLength函數(shù)
- 獲取UTF-8字符串的長度,使用GetStringUTFLength函數(shù)
- 創(chuàng)建Unicode字符串,使用NewStringUTF函數(shù)
- 從Java字符串轉(zhuǎn)換成C/C++字符串,使用GetStringUTFChars函數(shù)
- 通過GetStringUTFChars、GetStringChars、GetStringCritical獲取字符串,這些函數(shù)內(nèi)部會(huì)分配內(nèi)存,必須調(diào)用相對應(yīng)的ReleaseXXXX函數(shù)釋放內(nèi)存