今天開發中遇到一個需求:java調用.so或dll動態庫裏的方法後需要返回一個字符串給java使用,如以下方式:
JNIEXPORT jstring JNICALL Java_com_ygc_demo_jni_ApiNative_fromCharToJString(JNIEnv *, jclass);
請注意了這裏返回的是一個jstring,那我們怎麼返回這個java想要的string呢?這裏就用到了jni裏的NewStringUTF這個函數,具體的實現如下:
JNIEXPORT jstring JNICALL Java_com_ygc_demo_jni_ApiNative_fromCharToJString
(JNIEnv *env, jclass jc){
char Version[256] = {"Hello world!"};
jstring value = env->NewStringUTF((const char*)Version);
return value;
}
代碼很簡單不用解釋,這裏主要說的是NewStringUTF創建後返回的jstring要不要釋放內存的問題,剛開始我也糾結這個問題我的辦法就是在java層寫了個while(true){}的循環測試下到底內存是否出現問題,結果跑了一個上午程序依然正常使用,我的結論就是調用NewStringUTF之後返回是jstring不需要釋放,java的虛擬機會自動釋放這個內存,這個只是我的一個小測試,我又去openJdk裏去搜索這種返回jstring用法的代碼結果搜索後openJdk裏也沒有釋放內存的操作,代碼如下:
/*
* Class: sun_security_mscapi_Key
* Method: getKeyType
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_sun_security_mscapi_Key_getKeyType
(JNIEnv *env, jclass jclazz, jlong hCryptKey)
{
ALG_ID dwAlgId;
DWORD dwAlgIdLen = sizeof(ALG_ID);
if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) {
if (CALG_RSA_SIGN == dwAlgId) {
return env->NewStringUTF("Signature");
} else if (CALG_RSA_KEYX == dwAlgId) {
return env->NewStringUTF("Exchange");
} else {
char buffer[64];
if (sprintf(buffer, "%lu", dwAlgId)) {
return env->NewStringUTF(buffer);
}
}
}
return env->NewStringUTF("<Unknown>");
}
代碼二:
JNIEXPORT jstring JNICALL
Java_com_sun_java_util_jar_pack_NativeUnpack_getOption(JNIEnv *env, jobject pObj,
jstring pProp) {
unpacker* uPtr = get_unpacker(env, pObj);
CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL);
const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE);
CHECK_EXCEPTION_RETURN_VALUE(prop, NULL);
const char* value = uPtr->get_option(prop);
CHECK_EXCEPTION_RETURN_VALUE(value, NULL);
env->ReleaseStringUTFChars(pProp, prop);
return env->NewStringUTF(value);
}
結論:綜合上面我的測試和在openJdk裏搜索的使用方法得出的結論,NewStringUTF之後的返回給java層的jstring不需要釋放內存,但是局部使用的不返回給java層的建議還是調用下env->DeleteLocalRef(jstring);
如果我以上分析的結論或方法有誤的還請大牛提出我會及時改正,感謝你們查看我的文章。