Android NDK(JNI)詳解教程五 字符串操作

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)存
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容