JNI Freeing Memory to Avoid Memory Leak

2019-02-13 05:07发布

问题:

So i have this C++ program that is called via JNI from my Java program, the code follows:

    JNIEXPORT jstring JNICALL Java_com_entrust_adminservices_urs_examples_authn_LdapAuthenticator2_takeInfo(JNIEnv *env, jobject obj, jstring domain, jstring id, jstring idca, jstring password) 
{
    const char *nt_domain;
    const char *nt_id;
    const char *nt_password;
    HANDLE hToken = 0;

    bool aut = false;

    nt_domain = env->GetStringUTFChars(domain, NULL);
    nt_id = env->GetStringUTFChars(id, NULL);
    nt_password = env->GetStringUTFChars(password, NULL);

      aut = LogonUser(nt_id, nt_domain, nt_password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken );

      /* release buffers */
    env->ReleaseStringUTFChars(domain, nt_domain);
    env->ReleaseStringUTFChars(id, nt_id);
    env->ReleaseStringUTFChars(password, nt_password);
    /* release the login handle */
    CloseHandle(hToken);

    if(aut)
    {
        return env->NewStringUTF("true"); 
    }

    DWORD dwError = GetLastError();
      LPVOID lpMsgBuf;

      FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL );

    return env->NewStringUTF((const char*)lpMsgBuf); //returns the contents of lpMsgBuf (error)
}

in that second to last line jstring newString = env->NewStringUTF((const char*)otherString); is never released, but returned, will it cause an eventual memory leak? is there anyway to get around this?

Also is it possible that instead of returning a string i return a boolean (as returned by the LogonUser function), instead of a jstring, and instead add an "errormessage" refrence to be passed in the method, and update that? will my Java program be able to see an update to "errormessage"?

Thanks.

回答1:

NewStringUTF() creates a new java.lang.String -- in other words, an object on the Java heap, which will get collected when there are no more references to it.

Or are you asking about otherString? I don't know what FormatMessage does, but it looks like it's allocating memory on the C heap. If that's the case, then yes, you have to explicitly free that memory.

You make your life harder by sometimes setting otherString to a constant string. Don't do that. Instead, call NewStringUTF() within the blocks of your if/else, and in the second case free the native C string.



回答2:

You don't have to worry about the memory allocated by NewStringUTF as that will be taken care of by the Java garbage collector.

But you have to free the lpMsgBuf as you are passing FORMAT_MESSAGE_ALLOCATE_BUFFER to FormatMessage (i.e. you have to use LocalFree to free that buffer), see the FormatMessage documentation.