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

C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。

本篇主要讲解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);
}

原文 

https://www.jakeprim.cn/2019/01/05/ndk2/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 01-05 JNI编程-动态注册及native线程调用Java

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址