J'ai lu des choses sur JNI et je n'arrive pas à comprendre ce qui se passe si un thread démarre -> appelle AttachCurrentThread () -> passe des appels JNI -> quitte le thread.
Idéalement, nous devrions appeler DetachCurrentThread () avant la fermeture du thread, cependant, quelles sont les implications si l'application ne le fait pas? Cela entraînerait-il une fuite de mémoire ou tout autre problème?
Ne pas appeler DetachCurrentThread()
provoquera définitivement une fuite de mémoire; les autres conséquences sont spécifiques à la JVM, et probablement non pertinent pour les applications Android, où la JVM s'arrête à la fin du processus. Il existe de nombreux wrappers C++ qui aident à gérer le thread Attach/Detach, voir par exemple: http://w01fe.com/blog/2009/05/c-callbacks-into-Java-via-jni- plus facile
Mise à jour: 1000 grâce à fadden pour l'ouverture des yeux link; sur Dalvik, un thread qui se termine sans appeler DetachCurrentThread()
, amène l'ensemble VM et le processus se bloque.
Voici le logcat de l'émulateur officiel, mon code basé sur l'exemple HelloJni
de 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)
Voici la fonction appropriée ajoutée à 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 !");
}
Une belle implémentation de cette stratégie peut être trouvée dans WebRTC git repo .