今天开发中遇到一个需求: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);
如果我以上分析的结论或方法有误的还请大牛提出我会及时改正,感谢你们查看我的文章。