Android Studio3.0开发JNI流程------JNI静态注册和动态注册(多个类的native动态注册-经典篇)

本文详细介绍了Android Studio 3.0中JNI的静态和动态注册过程,重点讨论了JNI动态注册,包括原理、步骤和多个类的动态注册。通过动态注册,可以提高效率并实现模块化管理。文中提供了多类动态注册的实例代码,展示了如何将不同类的native方法分开处理,便于维护。
摘要由CSDN通过智能技术生成

网上关于多个类的动态注册以及管理案例太少啦……

静态注册其实不用多言,Android Studio默认的工程就是静态注册的。

静态注册

    一般在写C++代码都会有JNIEXPORT和JNICALL,这两个关键字是两个宏定义,它主要的作用就是说明该函数为JNI函数,在Java虚拟机加载的时候会链接对应的native方法。
    在Java虚拟机加载so库时,如果发现含有上面两个宏定义的函数时就会链接到对应Java层的native方法,那么怎么知道对应Java中的哪个类的哪个native方法呢,我们仔细观察JNI函数名的构成其实是:以Java为前缀,并且用“_”下划线将包名、类名以及native方法名连接起来就是对应的JNI函数了。
其实就是:Java+包名+类名+方法名(native方法)
例如:
Java_fj_clover_testjni_MainActivity_stringFromJNI( )

静态方法注册JNI有哪些弊端?
1. 必须遵循某些规则
2. 名字过长
3. 多个class需Javah多遍,其实Android Studio中可不用这么做
4. 运行时去找效率不高

好了说了那么多,那么我们来讲解JNI动态注册。

动态注册

动态注册:在JNi层实现的,JAVA层不需要关心,因为在system.load时就会去调用JNI_OnLoad,有就注册,没就不注册。

动态注册的原理:JNI 允许我们提供一个函数映射表,注册给 JVM,这样 JVM 就可以用函数映射表来调用相应的函数,
而不必通过函数名来查找相关函数(这个查找效率很低,函数名超级长)。

动态注册的过程

第一步:参数映射表,就是需要注册的函数列表,放在JNINativeMethod 类型的数组中,只要有native方法就在这里添加。

//参数映射表
//这是在MainActivity中的native方法
static JNINativeMethod gMethods_MainActivity[] = {
        {
  "stringFromJNI", "()Ljava/lang/String;",(void *) stringFromJNI},
        {
  "setString","(Ljava/lang/String;)Ljava/lang/String;",(void *) setString},
};

参数说明:
参数1:就是java代码中用native关键字声明的函数名字符串
参数2:native方法的签名(参数类型和返回值类型)
参数3:C/C++中对应函数的函数名(地址)

参数1的名称是对应Java中的native方法名,但是参数3的名称可以随意取,为了知名见义可以与native方法名保持一致。

第二步:注册native方法

//找到MainActivity.java类
static int registerNatives(JNIEnv *engv) {

    jclass clazz;
    clazz = engv->FindClass("fj/clover/differentclassregister/MainActivity");   //找到类

    if (clazz == NULL) {
        return JNI_FALSE;
    }
    //int len = sizeof(methods) / sizeof(methods[0]);
    if (engv->RegisterNatives(clazz, gMethods_MainActivity,sizeof(gMethods_MainActivity) / sizeof(gMethods_MainActivity[0])) <
        0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

第三步:加载jni

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
    //为了方便管理我们将不同java类中的native方法分别注册
    registerNatives_HongBao(env); //注册MainActivity类的native方法
    return JNI_VERSION_1_4;
}

当 JVM 执行到 System.loadLibrary() 函数时,会立即调用 JNI_OnLoad() 方法,因此在该方法中进行各种资

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值