JNI回调时线程安全的处理

在网上能找到有关

“在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");
 
时间: 2024-11-04 21:28:51

JNI回调时线程安全的处理的相关文章

jni回调多线程问题

解决jni回调不同线程获取jvm问题 原文地址:https://blog.51cto.com/lindt/2472103

转载 多线程开发时线程局部变量的使用

多线程开发时线程局部变量的使用 http://blog.csdn.net/zsxxsz/article/details/6284759 2011-03-28 22:37197人阅读评论(0)收藏举报 一.概述 现在多核时代多线程开发越来越重要了,多线程相比于多进程有诸多优势(当然也有诸多劣势).在早期C的库中,有许多函数是线程不安全的,因为内 部用到了静态变量,比如:char *strtok(char *s, const char *delim); 该函数内部就有一个静态指针,如果多个线程同时调

浅析在项目开发(使用Delegate回调时)如何正确使用ARC

ARC(自动引用计数)是2011年伴随iOS5来的一项技术.简单来说就是通过LLVM3.0编译器帮助程序处理“一大部分”OC中的内存管理.为什么是“一大部分”,这个等会儿解释. 一直以来内存管理这个话题都是初学iOS开发,初学OC语言必须要面对的知识点,也是大家容易出错的地方.对象释放后调用会造成crash.不释放的对象会造成内存泄漏这些问题困扰着初学者.ARC的到来按理说应该是福音,不需要自己管理内存了嘛,多简单.但是随之而来的两个问题:1,我发现周围有些拥有2-5年开发经验的“半老手”(要谦

JNI 回调小记

javah在eclipse中设置参数:location(javah.exe的位置)working dir(${project_loc}/src) -classpath .;./classes -d ${project_loc}\jni -jni ${java_type_name} 回调的java代码 public class HelloWorld { static { System.loadLibrary("jnidemo"); } public void myCallbackFunc

day 32异步+回调、线程queue、线程Event、协程、单线程下实现遇到IO切换

一.异步+回调:线程是谁空谁调,进程是主进程调用 from concurrent.futures import ProcessPoolExcutor,ThreadPoolExecutor from threading import current_thread import requests,os,time,random def get(url): print('%s GET %s'%(current_thread().name,url)) response=requests.get(url)

jni不通过线程c回调java的函数

整个工程的项目如下: 1.项目的思路是在activity中启动MyService这个服务,在服务中调用 JniScsManger类中的本地方法startNativeScsService,在 startNativeScsService的c代码实现中回调JniScsManger中的scsConnectStatus方法.下面我们来看下两种代码的实现: package com.cetcs.ecmapplication.jni.scs; import android.app.Service; import

android使用c通过jni回调java

很多场合都有这样的需求,由于以前都是java调用c的接口,没有做过回调,今天花了大半天时间把这个流程跑通了,记录一下,以备后用.这里发句牢骚,那些网上分享出来的代码,请问你们确实是能正常工作吗?还有查来查去都是那几份,大家转载精神可嘉啊 jni相关头文件代码 /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class com_example_ndktest_CallbackTest */ #

Android中JNI调用时出现accessed stale local reference的问题

之前在做一个native的模块时遇到这样一个问题: 代码运行在android2.3上没有任何问题,可是在4.2上运行时报出了:JNI ERROR (app bug): accessed stale local reference 的错误. 后来在StackOverflow上找到了问题的答案.简单来说就是  4.0以上的android系统GC在垃圾回收时为了减少内存碎片,会对内存进行整理,整理时必然会移动对象的内存地址,这时C代码的指针还指向原来对象的地址,这时该对象已经被移动到了其他位置,因此会

QQ互联,填写回调时注意事项

今天在做QQ登录接口的时候,填写回调地址的时候,竟然出现了诡异的事情. 我的回调地址我直接填的域名,也申请通过了.但是在做开发地时候,一直提示这蛋疼的  redirect uri is illegal(100010)  ,然后就各种查资料,都是说我的回调地址 填的有问题,于是我又查帮助文档,看到了这样的 申请时填写的callback是:mysite.com;example.com 合法的回调地址可以是:http://bbs.mysite.com/qqlogin.php?a=1 也可以是:http