gogoWebsite

Does the NewStringUTF function in jni need to be freed after it is called?

Updated to 2 days ago

Today, I encountered a requirement in development: after java calls .so or dll dynamic library methods, I need to return a string for java to use, such as the following method:

JNIEXPORT jstring JNICALL Java_com_ygc_demo_jni_ApiNative_fromCharToJString(JNIEnv *, jclass);

Please note that the returned jstring here is a jstring, so how do we return the string we want in java? Here I use the jniNewStringUTFThe specific implementation of this function is as follows:

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;
}

The code is very simple and needs no explanation. What we mainly talk about here isQuestion about whether the jstring returned after NewStringUTF is created to release memoryAt the beginning, I was also confused about this problem. My solution was to write a while (true) {} loop test in the java layer to see if there was any problem with the memory. As a result, the program was still used normally after running for a morning. My conclusion was to call it.NewStringUTFThen the return is that jstring does not need to be released, and the java virtual machine automatically releases this memory. This is just a small test of mine. I went to openJdk to search for the code that returns jstring usage, and the result of searching, there is no operation to release memory in openJdk. The code is as follows:

/*
 * 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>");
}

Code 2:

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);
}

in conclusion:Based on the above test and the conclusions drawn by the usage method searched in openJdk, the jstring returned to the java layer after NewStringUTF does not need to free memory, but the suggestion for local use does not return to the java layer is to call the env->DeleteLocalRef(jstring);

If the conclusions or methods of my above analysis are wrong, please ask Daniu to suggest that I will correct them in time. Thank you for viewing my article.