2014-10-23 16 views
12

Ho letto cose su JNI e non riesco a capire cosa succede se inizia un thread -> chiama AttachCurrentThread() -> effettua alcune chiamate JNI -> thread exit.JNI Android - Chiama AttachCurrentThread senza DetachCurrentThread

Idealmente, dovremmo chiamare DetachCurrentThread() prima della chiusura del thread, tuttavia, quali sono le implicazioni se l'app non lo fa? Provocherebbe perdita di memoria o altri problemi?

+0

noti che è solo dovrebbe chiama 'DetachCurrentThread()' se hai collegato il thread. Il comportamento che separa il thread corrente se si tratta di un thread di proprietà di JVM non è definito. – technomage

risposta

20

Non chiamare DetachCurrentThread() causerà sicuramente una perdita di memoria; altre conseguenze sono specifiche JVM, e probabilmente non pertinenti per le app Android, dove la JVM si arresta quando il processo termina. Ci sono un bel po 'wrapper C++ che aiutano a gestire filo montare/smontare, si veda ad esempio: http://w01fe.com/blog/2009/05/c-callbacks-into-java-via-jni-made-easyier

Aggiornamento: 1000 grazie alla fadden per l'occhio-apertura link; su Dalvik, un thread che esce senza chiamare DetachCurrentThread(), porta l'intera VM e il processo a crash.

Ecco il logcat dall'emulatore ufficiale, il mio codice basato sul campione HelloJni da 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) 

Ecco la funzione rilevante aggiunto 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 !"); 
} 
+0

Non riesco ad accedere al collegamento. – pree

+0

Inoltre, se si crea un numero elevato di thread e si chiama attachcurrentthread senza scollegarsi, è possibile che si verifichi una perdita di memoria. Tuttavia, cosa succede se ci sono alcuni lunghi thread in esecuzione e escono senza chiamare detachcurrentthread. Quale sarebbe l'impatto? Non si stacca automaticamente una volta che è uscito? – pree

+0

No, i thread non si "staccano automaticamente" finché il processo (e JVM, su Android entrambi si verificano contemporaneamente) viene chiuso. Come ho già detto, su altre piattaforme, dove JVM può sopravvivere a un processo o viceversa, l'effetto potrebbe essere più doloroso. Inoltre, la perdita può essere molto significativa, questo dipende da come il thread specifico gestisce il suo JNI. –

Problemi correlati