JNI回调时线程安全的处理

来源:互联网 发布:mac版围棋对弈软件 编辑:程序博客网 时间:2024/06/01 15:00

在网上能找到有关

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


1 0
原创粉丝点击