JNIk开发过程中遇到的多线程处理问题

最近在Android项目中要用到JNI,在C代码中,除了主线程外,还需要创建两个子线程,并且在子线程中回调了Java中的方法,因为对JNI模块不太熟悉,在开发过程中遇到了不少问题,今天主要记录下在子线程中回调Java中方法的问题。
刚开始,我的代码是这么写的,然后运行程序之后,就会崩溃:
JNIEnv* env;
void CallBackJavaMethod_T1(jobject obj, jstring str){
    jclass clazz = (**env).FindClass(env, "com/example/jnidatapass/JNI");
    jmethodID jmid = (**env).GetMethodID(env, clazz, "printStirng","(Ljava/lang/String;)V");
    jobject jobj = (**env).AllocObject(env, clazz);
    (**env).CallVoidMethod(env, jobj, jmid,str);
}
后来,在网上查询之后,才发现问题出在JNIEnv*变量上,JNIEnv*是和线程Thread对应的,每一个线程都有对应的JNIEnv对象,上面写的代码之所以报错,是因为在这个方法中,用到的JNIEnv*变量,是主线程中的,但这个函数是在子线程中调用的,所以,Exception。
修改后成功运行的代码:
void CallBackJavaMethod_T1(jobject obj, jstring str){
    JNIEnv *env;
    JavaVM *jvm;
    int result, status;
    status = jvm->GetEnv(jvm, (void**) &env, JNI_VERSION_1_2);
    if (status < 0) {
        JavaVMAttachArgs args;
        args.version = JNI_VERSION_1_2;
        args.name = "user";
        args.group = NULL;
        result = (jvm)->AttachCurrentThread(jvm, (JNIEnv **) &env, &args);
        if (result < 0) {
            printError("event_dispatcher_log AttachCurrentThread failed");
        }
    }
    jclass clazz = (**env).FindClass(env, "com/example/jnidatapass/JNI");
    jmethodID jmid = (**env).GetMethodID(env, clazz, "printStirng",
            "(Ljava/lang/String;)V");
    jobject jobj = (**env).AllocObject(env, clazz);
    (**env).CallVoidMethod(env, jobj, jmid, str);
    if(status<0)
        jvm->DetachCurrentThread(jvm);
}
如代码所示,在子线程调用的时候,获取了当前子线程的JNIEnv*对象,如果返回的是NULL,说明当前子线程还没有绑定JNIEnv*对象,需要通过AttachCurrentThread方法,传入一个JNIEnv*变量,之后就可以直接使用这个变量了。(在线程结束或者不在使用JNIEnv*的时候,需要调用DetachCurrentThread,解除绑定)。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值