Android JNI - 调用AttachCurrentThread而不使用DetachCurrentThread

pre*_*ree 17 java-native-interface android android-ndk

我一直在阅读关于JNI的东西,似乎无法弄清楚如果线程启动会发生什么 - >调用AttachCurrentThread() - >进行一些JNI调用 - >线程退出.

理想情况下,我们应该在线程退出之前调用DetachCurrentThread(),但是,如果应用程序没有这样做会有什么影响?它会导致内存泄漏或任何其他问题吗?

Ale*_*ohn 27

不调用DetachCurrentThread()肯定会导致内存泄漏; 其他后果是特定 JVM的,并且可能与Android应用无关,其中JVM在进程退出时关闭.有很多C++包装器可以帮助管理线程Attach/Detach,例如:http: //w01fe.com/blog/2009/05/c-callbacks-into-java-via-jni-made-easyier

更新: 1000个感谢法登为睁眼链接 ; 在Dalvik上,一个没有调用退出的线程DetachCurrentThread(),会导致整个虚拟机和进程崩溃.

这是来自官方模拟器的logcat,我的代码基于HelloJni来自NDK 的样本:

10-26 04:16:25.853: D/dalvikvm(1554): Trying to load lib /data/app-lib/com.example.hellojni-2/libhello-jni.so 0xb3d264f0
10-26 04:16:25.893: D/dalvikvm(1554): Added shared lib /data/app-lib/com.example.hellojni-2/libhello-jni.so 0xb3d264f0
10-26 04:16:25.893: D/dalvikvm(1554): No JNI_OnLoad found in /data/app-lib/com.example.hellojni-2/libhello-jni.so 0xb3d264f0, skipping init
10-26 04:16:26.463: D/gralloc_goldfish(1554): Emulator without GPU emulation detected.
10-26 04:16:31.033: D/threadFunction(1554): Attaching
10-26 04:16:31.173: D/threadFunction(1554): Not Detaching
10-26 04:16:31.183: D/dalvikvm(1554): threadid=11: thread exiting, not yet detached (count=0)
10-26 04:16:31.193: D/dalvikvm(1554): threadid=11: thread exiting, not yet detached (count=1)
10-26 04:16:31.193: E/dalvikvm(1554): threadid=11: native thread exited without detaching
10-26 04:16:31.193: E/dalvikvm(1554): VM aborting
10-26 04:16:31.213: A/libc(1554): Fatal signal 6 (SIGABRT) at 0x00000612 (code=-6), thread 1567 (xample.hellojni)
Run Code Online (Sandbox Code Playgroud)

以下是添加到的相关功能hello-jni.c:

static JavaVM* jvm = 0;
static jobject activity = 0; // GlobalRef

void* threadFunction(void* irrelevant)
{
    JNIEnv* env;
    usleep(5000000);

    __android_log_print(ANDROID_LOG_DEBUG, "threadFunction", "Attaching");

    (*jvm)->AttachCurrentThread(jvm, &env, NULL);

    jclass clazz = (*env)->GetObjectClass(env, activity);
    jmethodID methodID = (*env)->GetMethodID(env, clazz, "finish", "()V" );
    (*env)->CallVoidMethod(env, activity, methodID);

    __android_log_print(ANDROID_LOG_DEBUG, "threadFunction", "Not Detaching");
//    (*jvm)->DetachCurrentThread(jvm);
}

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    (*env)->GetJavaVM(env, &jvm);
    activity = (*env)->NewGlobalRef(env, thiz);

    pthread_t hThread;
    pthread_create(&hThread, NULL, &threadFunction, NULL);
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Run Code Online (Sandbox Code Playgroud)

可以在WebRTC git repo中找到该策略的一个很好的实现.

  • 如果一个线程附加然后暂停而没有分离,Dalivk VM将中止,因此资源泄漏不会被忽视.请参阅https://android.googlesource.com/platform/dalvik/+/kitkat-release/vm/Thread.cpp中的第1035行threadExitCheck(). (6认同)