Android JNI - Call AttachCurrentThread without DetachCurrentThread

前端 未结 1 1847
醉梦人生
醉梦人生 2020-12-02 21:31

I have been reading about JNI stuff and can\'t seem to figure out what happens if a thread starts -> calls AttachCurrentThread() -> make some JNI calls -> thread exit.

相关标签:
1条回答
  • 2020-12-02 21:54

    Not calling DetachCurrentThread() will definitely cause a memory leak; other consequences are JVM-specific, and probably irrelevant for Android apps, where the JVM shuts down when the process exits. There are quite a few C++ wrappers that help to manage thread Attach/Detach, see for example: http://w01fe.com/blog/2009/05/c-callbacks-into-java-via-jni-made-easyier

    Update: 1000 thanks to fadden for the eye-opening link; on Dalvik, a thread that exits without calling DetachCurrentThread(), brings the whole VM and the process crashing down.

    Here is the logcat from the official emulator, my code based on the HelloJni sample from 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)
    

    Here is the relevant function added to 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 !");
    }
    

    A nice implementation of this strategy can be found in WebRTC git repo.

    0 讨论(0)
提交回复
热议问题