在网上能找到有关
“在Jni中通过 env->CallStaticVoidMethod去做callback的时候,总会挂掉 原因是JniEnv是和线程相关的,只能在对应创建的线程中使用 而JVM却是进程相关的,可以通过JVM来获取线程相关的JNIENV。”
关于这个的解决办法,能搜到的都基本一模一样。变量名都不带改的。
比如:http://blog.chinaunix.net/uid-21564437-id-3343209.html
http://my.oschina.net/u/97468/blog/383492
基本都是通过
fields.pjvm->AttachCurrentThread(&env, NULL); env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg); Fields.pjvm->DetachCurrentThread();
这种方式来解决线程问题。
今天偶然发现一种挺好的方式:
JNIEXPORT jint JNICALL Reset (JNIEnv *env, jclass cls) { SET_ENV(env); ..... } void SET_ENV(JNIEnv* env) { pid_t tid = syscall(__NR_gettid); // current thread id g_JNIENV_Map[tid] = env; }
下面这部分是抄来的
//system call number:
#define __NR_gettid 224
因此,要获取某个线程的TID,最nasty的方式是:
1. #include <sys/syscall.h>
2. printf("The ID of this thread is: %ld\n", (long int)syscall(224));
或者比较elegant的方式是:
1. #include <sys/syscall.h>
2. #define gettidv1() syscall(__NR_gettid)
3. #define gettidv2() syscall(SYS_gettid)
4. printf("The ID of this thread is: %ld\n", (long int)gettidv1());// 最新的方式
5. printf("The ID of this thread is: %ld\n", (long int)gettidv2());// traditional form
PS: 在/usr/include/sys/syscall.h中可以看到关于__NR_<name>和SYS_<name>两个宏的区别,实际最后使用的都是__NR_<name>。
就是为了证明这代码是获取当前线程ID的(Linux)
pid_t tid = syscall(__NR_gettid); // current thread id
JNIEnv* GET_ENV() { pid_t tid = syscall(__NR_gettid); // current thread id map<pid_t, JNIEnv*>::iterator it = g_JNIENV_Map.find(tid); if (it == g_JNIENV_Map.end()) { return NULL; } else { return it->second; } } 这样,你在需要使用env的时候就能根据当前线程找到对应的正确的env指针了。 JNIEnv *env = GET_ENV(); jclass cls = env->FindClass(XXX); jmethodID methodId = env->GetStaticMethodID(cls, "showDialog", "()V");