美文网首页Android-NDK/JNINDK
JNI编程-动态注册及native线程调用Java

JNI编程-动态注册及native线程调用Java

作者: 289346a467da | 来源:发表于2018-10-27 21:44 被阅读7次

    本篇主要讲解JNI的一些高级写法和线程,文章内容都非常简单。

    JNI_OnLoad

    上一章讲的JNI 编程详解
    Java 要调用C++的方法,都要写一大长串比如:

    extern "C"
    JNIEXPORT void JNICALL
    Java_com_jnimode1_MainActivity_updateGolbal(JNIEnv *env, jobject instance, jclass jclass1)
    

    上述相当于静态注册,而JNI_OnLoad是动态注册,两者其实没什么区别,简化了方法名让人更容易理解。

    简化后

    void updateGolbal(jclass cls)
    

    下面我们看一个例子就理解了,都有注释,so easy

    JavaVM *_vm;
    
    void dynamicTest() {
        LOGE("我是被动态注册的方法dynamicTest");
    }
    
    //JNIEnv *env, jobject instance 如果传参数这两个参数必须存在
    jint dynamicTest2(JNIEnv *env, jobject instance, jint i) {
        LOGE("我是被动态注册的方法dynamicTest2");
        return i;
    }
    
    //静态的Jni native 方法数组
    static const JNINativeMethod method[] = {
            //方法名    签名    本地方法
            {"dynamicJavaTest",  "()V",  (void *) dynamicTest},
            {"dynamicJavaTest2", "(I)I", (int *) dynamicTest2}
    };
    
    //类名
    static const char *mClassName = "com/jnimode1/MainActivity";
    
    //返回Jni 版本
    int JNI_OnLoad(JavaVM *vm, void *r) {
        LOGE("JNI_OnLoad");
        _vm = vm;
        JNIEnv *env = 0;
        //获得JNIEnv 这里会返回一个值 小于0 代表失败
        jint res = vm->GetEnv((void **) (&env), JNI_VERSION_1_6);
        //判断返回结果
        if (res != JNI_OK) {
            return -1;
        }
        //根据类名找到类,注意有native的类不能被混淆
        jclass jcls = env->FindClass(mClassName);
        //动态注册  第一个参数 类  第二个参数 方法数组  第三个参数 注册多少个方法
        env->RegisterNatives(jcls, method, sizeof(method) / sizeof(JNINativeMethod));
        return JNI_VERSION_1_6;
    }
    

    Activity 中调用

    public native void dynamicJavaTest();
    
        public native int dynamicJavaTest2(int i);
    

    native线程调用Java

    native调用java需要使用JNIEnv这个结构体,而JNIEnv是由Jvm传入与线程相关的变量。

    但是可以通过JavaVM的AttachCurrentThread方法来获取到当前线程中的JNIEnv指针。

    jobject _instance;
    
    void *task(void *args){
         JNIEnv *env;
    
        //将本地当前线程附加到 jvm 并获得jnienv
        //成功则返回0
        jint res = _vm->AttachCurrentThread(&env,0);
    
        if (res != JNI_OK){
            return 0;
        }
    
        jclass jclass1 = env->GetObjectClass(_instance);
    
        jmethodID staticMethod = env->GetStaticMethodID(jclass1,"staticMothed","(I)V");
    
        env->CallStaticVoidMethod(jclass1,staticMethod,100);
    
    
        jmethodID  jmethodID1 = env->GetMethodID(jclass1,"instanceMothed","(Ljava/lang/String;)V");
    
        jstring jstring1 = env->NewStringUTF("我是C++");
    
    
    
        env->CallVoidMethod(_instance,jmethodID1,jstring1);
    
        env->DeleteLocalRef(jclass1);
        env->DeleteLocalRef(jstring1);
        env->DeleteGlobalRef(_instance);
    
        //分离
        _vm->DetachCurrentThread();
    
        return 0;
    
    }
    
    
    void nativeThread2(JNIEnv *env,jobject instace){
        _instance = env->NewGlobalRef(instace);//_instacne 设置为全局引用
        pthread_t pthread;
        pthread_create(&pthread,0,task,0);
    }
    

    相关文章

      网友评论

        本文标题:JNI编程-动态注册及native线程调用Java

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