美文网首页
C++子线程中调用java方法

C++子线程中调用java方法

作者: 航行在蓝天的蚂蚱 | 来源:发表于2018-05-06 22:54 被阅读51次

    我们通常都是在C++主线程中调用java方法,很简单,但是在子线程中调用java方法却不能采用在主线程中调用的方式,因为调用java方法是要用JNIEnv去调用的,但是JNIEnv是线程相关的,子线程中不能直接使用创建线程的JNIEnv,所以需要JVM进程相关的,可以通过JVM来获取当前线程的JNIEnv,然后就可以调用java方法了。

    #include "JavaListener.h"
    
    JavaListener::JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj) {
        this->jvm = vm;
        this->jenv = env;
        this->jobj = obj;
    
        jclass  clz = env->GetObjectClass(jobj);
        if(!clz){
            return;
        }
        jmid = env->GetMethodID(clz,"onError","(ILjava/lang/String;)V");
    }
    
    
    /**
     *调用java方法
     * @param type 0:子线程,1:主线程
     * @param code
     * @param msg
     */
    void JavaListener::onError(int type, int code, const char *msg) {
        if(type == 0){
            JNIEnv *env;
            //初始化当前线程的JNIEnv
            jvm->AttachCurrentThread(&env,0);
            jstring jmsg = env->NewStringUTF(msg);
            env->CallVoidMethod(jobj,jmid,code,jmsg);
            env->DeleteLocalRef(jmsg);
            //释放当前线程的引用
            jvm->DetachCurrentThread();
        }else if(type == 1){
            jstring jmsg = jenv->NewStringUTF(msg);
            jenv->CallVoidMethod(jobj,jmid,code,jmsg);
            jenv->DeleteLocalRef(jmsg);
        }
    }
    
    pthread_t thread;
    //子线程执行体
    void *normalCallBack(void *data){
        LOG("Create C++ normal thread!");
        pthread_exit(&thread);
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_xy_jni_jnithreaddemo_feature_JniThread_createNormalThread(JNIEnv *env, jobject instance) {
        //创建子线程
        pthread_create(&thread,NULL,normalCallBack,NULL);
    }
    
    
    #include "JavaListener.h"
    JavaVM *jvm;
    //初始化JavaVM
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,void* reserved){
        JNIEnv *env;
        jvm = vm;
        if(vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK){
            return -1;
        }
        return JNI_VERSION_1_6;
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_xy_jni_jnithreaddemo_feature_JniThread_callbackJavaFromC(JNIEnv *env, jobject instance) {
        javaListener = new JavaListener(jvm,env,env->NewGlobalRef(instance));
        //主线程中调用
    //    javaListener->onError(1,100,"c++ call java meid from main thread!");
        //开启子线调用
        pthread_create(&child_thread,NULL,childCallback,javaListener);
    }
    

    主要步骤就是,通过运行时函数JNI_OnLoad初始化JavaVM,再通过JavaVM调用AttachCurrentThread函数初始化当前线程的JNIEnv,此时这个JNIEnv就可以调用java方法了,调用完后要调用JavaVM的DetachCurrentThread函数来释放JavaVM引用。

    相关文章

      网友评论

          本文标题:C++子线程中调用java方法

          本文链接:https://www.haomeiwen.com/subject/zeyprftx.html