web-dev-qa-db-ja.com

Android JNI-DetachCurrentThreadなしでAttachCurrentThreadを呼び出す

私はJNIに関するものを読んでいて、スレッドが開始した場合-> AttachCurrentThread()を呼び出した場合->いくつかのJNI呼び出しを行った場合->スレッドが終了した場合にどうなるか理解できません。

理想的には、スレッドが終了する前にDetachCurrentThread()を呼び出す必要がありますが、アプリがそれを行わない場合、どのような影響がありますか?メモリリークやその他の問題が発生しますか?

17
pree

DetachCurrentThread()を呼び出さないと、必ずメモリリークが発生します。その他の影響はJVM固有であり、 Androidアプリの場合、プロセスが終了するとJVMがシャットダウンするため、おそらく無関係です。。スレッドのAttach/Detachを管理するのに役立つC++ラッパーはかなりあります。たとえば、以下を参照してください。 http://w01fe.com/blog/2009/05/c-callbacks-into-Java-via-jni- made-easyier

更新:1000(faddenのおかげで目を見張るリンク; Dalvikでは、DetachCurrentThread()を呼び出さずに終了するスレッドは、VM全体をもたらし、プロセスがクラッシュします。

これは公式エミュレーターからのlogcatです。NDKの HelloJni サンプルに基づく私のコード:

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)

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

この戦略の素晴らしい実装は、WebRTC git repo にあります。

27
Alex Cohn