JNI回调时线程安全的处理

在网上能找到有关

在Jni中通过 env->CallStaticVoidMethod去做callback的时候,总会挂掉 原因是JniEnv是和线程相关的,只能在对应创建的线程中使用 而JVM却是进程相关的,可以通过JVM来获取线程相关的JNIENV。

关于这个的解决办法,能搜到的都基本一模一样。变量名都不带改的。

比如:http://blog.chinaunix.net/uid-21564437-id-3343209.html

基本都是通过

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


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。