前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是动态注册?什么是静态注册?

什么是动态注册?什么是静态注册?

原创
作者头像
派大星在吗
发布2021-12-18 11:07:50
1.9K0
发布2021-12-18 11:07:50
举报
文章被收录于专栏:我的技术专刊我的技术专刊

静态注册和动态注册

静态注册

默认情况下,就是静态注册,静态注册是最简单的方式,NDK开发过程中,基本上使用静态注册。前面的知识都是静态注册的方式。

优点: 开发简单

缺点:

  1. JNI函数名非常长
  2. 捆绑 上层 包名 + 类名
  3. 运行期 才会去 匹配JNI函数,性能上 低于 动态注册

动态注册

再看Android Framework源代码的Native层,Android 系统的C++源码:基本上都是动态注册。

动态注册是怎么玩转的?

明白一个简单的道理,Java中我们new

类,默认会调用构造函数,重写了构造函数,就会调用我们自己的。NDK中Jni函数也是这样,默认会有JNI_OnLoad

一系列函数,我们重写JNI_OnLoad来加载我们自己的逻辑。

当我们调用,System.loadLiberary("xxxxx");

<---->

实际上自动调用了JNI_OnLoad 做动态注册

先看下示例代码

➜ Java 部分

代码语言:txt
复制
public native void dynamicJavaM01();
代码语言:txt
复制
public native int dynamicJavaM01(String value);
代码语言:txt
复制
调用
代码语言:txt
复制
case R.id.jni_regist_1:
代码语言:txt
复制
                dynamicJavaM01();
代码语言:txt
复制
                break;
代码语言:txt
复制
 case R.id.jni_regist_2:
代码语言:txt
复制
                dynamicJavaM01("JNI动态注册,JNI传参");
代码语言:txt
复制
                break;

➜ C++ 部分

代码语言:txt
复制
#include "include/common_head.h"
代码语言:txt
复制
//JNIEnv *env, jobject thiz,  默认这两个参数是可以省略,如果不用的话
代码语言:txt
复制
//void dynamicM01(JNIEnv *env, jobject thiz)
代码语言:txt
复制
void dynamicM01() {
代码语言:txt
复制
    LOGD("我是动态注册的函数 dynamicM01...");
代码语言:txt
复制
}
代码语言:txt
复制
int dynamicM02(JNIEnv *env, jobject thiz, jstring value) {
代码语言:txt
复制
    const char * text = env->GetStringUTFChars(value, nullptr);
代码语言:txt
复制
    LOGD("我是动态注册的函数 dynamicM02...%s",text);
代码语言:txt
复制
    env->ReleaseStringUTFChars(value,text);
代码语言:txt
复制
    return 200;
代码语言:txt
复制
}
代码语言:txt
复制
JavaVM *javaVm;
代码语言:txt
复制
const char *class_name = "top/zcwfeng/jni/JavaJNIActivity";
代码语言:txt
复制
//name,signature,*
代码语言:txt
复制
static const JNINativeMethod methods[] = {
代码语言:txt
复制
        {"dynamicJavaM01", "()V",                   (void *) (dynamicM01)},
代码语言:txt
复制
        {"dynamicJavaM02", "(Ljava/lang/String;)I", (int *) (dynamicM02)},
代码语言:txt
复制
};
代码语言:txt
复制
jint JNI_OnLoad(JavaVM *vm, void *unused) {
代码语言:txt
复制
    ::javaVm = vm;
代码语言:txt
复制
    JNIEnv *jniEnv = nullptr;
代码语言:txt
复制
    int result = javaVm->GetEnv(reinterpret_cast<void **>(&jniEnv), JNI_VERSION_1_6);
代码语言:txt
复制
    //result 等与0 成功,默认不成文规则,封装库都是成功就是0【如ffmpeg库等】
代码语言:txt
复制
    if (result != JNI_OK) {
代码语言:txt
复制
        return -1;
代码语言:txt
复制
    }
代码语言:txt
复制
    LOGE("System.loadLibrary --->JNI Load init success");
代码语言:txt
复制
    jclass clazz = jniEnv->FindClass(class_name);
代码语言:txt
复制
    //RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
代码语言:txt
复制
    jniEnv->RegisterNatives(clazz, methods,sizeof(methods)/sizeof(JNINativeMethod));
代码语言:txt
复制
    LOGE("动态 注册 dynamic success");
代码语言:txt
复制
    return JNI_VERSION_1_6;// AS的JDK在JNI默认最高1.6  Java的JDKJNI 1.8
代码语言:txt
复制
}
  • JNI_OnLoad 中赋值我们用了域的方式,如:this.a = a ---> ::javaVm = vm
  • 默认不成文规则,C 中封装库都是成功就是0
  • AS的JDK目前JNI默认最高1.6 和 Java的JDK的JNI 1.8不同
  • JNI_OK 就是JNI提供的一些宏定义方便使用。
  • 动态注册的方法参数,JNIEnv *env 和 jobject thiz,如果没有用到是可以不放到参数列表中,没有影像。
  • 动态注册核心RegisterNatives

① 重写JNI_OnLoad

② JavaVM 初始化获取JNIEnv,并获取到jclass

③ 注册函数

代码语言:txt
复制
//RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)
代码语言:txt
复制
    jniEnv->RegisterNatives(clazz, methods,sizeof(methods)/sizeof(JNINativeMethod));

参数需要提供,所在的类,数组(包含需要动态注册的方法),数组的大小

小技巧,传入JNINativeMethod* 以为指针相当于我们定义一个数组

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 静态注册和动态注册
    • 静态注册
      • 动态注册
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档