java JNI 释放内存以避免内存泄漏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1533378/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:58:17  来源:igfitidea点击:

JNI Freeing Memory to Avoid Memory Leak

javac++memory-leaksjava-native-interface

提问by Petey B

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

所以我有这个 C++ 程序,它从我的 Java 程序中通过 JNI 调用,代码如下:

    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?

在倒数第二行jstring newString = env->NewStringUTF((const char*)otherString);永远不会释放,而是返回,它会导致最终的内存泄漏吗?有没有办法解决这个问题?

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"?

还有可能不是返回字符串,而是返回布尔值(由 LogonUser 函数返回),而不是 jstring,而是添加要在方法中传递的“错误消息”引用,并更新它?我的 Java 程序能否看到“错误消息”的更新?

Thanks.

谢谢。

回答by kdgregory

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.

NewStringUTF()创建一个新的 java.lang.String —— 换句话说,Java 堆上的一个对象,当不再有对它的引用时将被收集。

Or are you asking about otherString? I don't know what FormatMessagedoes, 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.

或者你在问什么otherString?我不知道是什么FormatMessage,但它看起来像是在 C 堆上分配内存。如果是这种情况,那么是的,您必须明确释放该内存。

You make your life harder by sometimes setting otherStringto 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.

有时设置otherString为常量字符串会使您的生活更加艰难。不要那样做。相反,NewStringUTF()在 if/else 的块内调用,在第二种情况下释放本机 C 字符串。

回答by cmeerw

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

您不必担心 NewStringUTF 分配的内存,因为这将由 Java 垃圾收集器处理。

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 FormatMessagedocumentation.

但是您必须在将 FORMAT_MESSAGE_ALLOCATE_BUFFER 传递给 FormatMessage 时释放 lpMsgBuf(即您必须使用 LocalFree 来释放该缓冲区),请参阅FormatMessage文档。