linux下使用jni实现c++调用java程序(3)多线程jni使用

jni调用c++代码时,若c++实现里面采用了多线程,则会出现jvm crash的情况。
查了一下jni的说明,其中提到: JNIEnv *env指针和 jobject对象都不能跨线程使用,但是java虚拟机jvm可以共享

对于jobject,解决办法是

    a、glb_obj = glb_env->NewGlobalRef(obj);           //创建一个全局变量  

    b、jobject obj = glb_env->AllocObject(glb_cls);    //在每个线程中都生成一个对象

 

对于JNIEnv,解决办法是在每个线程中都重新生成一个env

    a、JNIEnv *env;  

    b、glb_jvm->AttachCurrentThread((void **)&env, NULL);

必须是原本就是Java线程(Java代码通过JNI调用native代码时,发起调用的那个肯定是Java线程),或者是让已有的native线程通过JNI来attach到Java环境。
你的每个“C++线程”里都应该要调用AttachCurrentThread()来确保它确实attach到Java环境里了。 

so,
jni应用于多线程程序时,我的处理办法是:
(1)主程序运行时,创建jvm和初始化jni,之后的每个线程就只调用GetJavaVM和CallObjectMethod就行了:
glb_env=queryer->createJVM();
int tmp=glb_env->GetJavaVM(&glb_jvm);
queryer->initJNI(glb_env);
queryer->queryExecute(glb_env);
(2)设置全局变量,达到共享jvm的效果:
JavaVM* glb_jvm;
jobject glb_obj;
JNIEnv* glb_env;
jclass glb_cls;
JenaQuery* queryer = new JenaQuery;
(3)对于每个线程,首先:
glb_jvm->AttachCurrentThread((void **) &env, NULL);//attach 当前线程到jvm中
env->MonitorEnter(glb_obj);//进入监控的java对象glb_obj,没一个java对象都有一个相关联的监视器
              env->PushLocalFrame(100);               //创建一个新的本地参考帧
(4) 之后就可以FindClass、GetMethodID、NewObject、CallObjectMethod调用java类中的函数了,最后记得:
            DetachCurrentThread();
(5)只有最后main函数退出之前,才没有线程在等待,这是才可以有效地DestroyJavaVM();



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值