Android JNI之动态注册(android studio)

故事得从这里开始-静态注册

没有对比,就没有伤害。静态注册自出生以来,就非议颇多。繁琐的过程(javah生成头文件),每增加一个接口,渣握h一下。长长长的函数名称,一个详细的身份证明。运行效率较低,第一次进行交流的时候,根据详细的身份去jni中查找对应身份的人,这个难度比较大,一个一个去对比,运气好,一次匹配就建立了关系,如果,假如说如果,等到最后,黄花菜都凉了。艰难的时候,到了要放弃的时候,man是时候登场了,动态注册,对,就是他。JNI中有一个函数映射表,注册给Jave虚拟机,一见钟情,交流就是这么顺畅。

动态注册,是需要画几个圈

规则,还是要有的。早早建立数据库,交流一触即发。

一。入口 JNI_OnLoad 方法

System.loadLibrary加载完 JNI 动态库之后,调用JNI_OnLoad函数,开始动态注册。这里就是报名注册的地方,地方不能找错,你报个警抓小偷,非要打个119,我也很悲伤,但无能为力。注意:一个.so只能存在一个onload方法。

二。重头戏 RegisterNatives 方法

在 JNI 帝国中,不得不介绍下 JNIEnv*,JVM代言人,掌握java生杀大权,java环境变量指针,是一个包含了JVM接口的结构,它包含了与JVM进行交互以及与Java对象协同工作所必需的函数。而 RegisterNatives 只是其中的一颗棋子,登记员。但只有通过他,你才能进入函数映射表。函数映射表?不急,我们慢慢来,一步一步剥离他的心。在 jni.h 帝国中,描述有这么一段:

typedef struct { 
    const char* name; //Java中函数的名字
    const char* signature; //描述了函数的参数和返回值
    void* fnPtr; //函数指针,指向我们调用别人家c++的封装 JNI 函数方法
} JNINativeMethod; 

这就是函数映射表的数据结构,注释加上,似乎也没什么需要解释的了,至于繁琐的源代码解析,这个结构又是怎么被使用,脑补,脑补。咳咳咳,回归正题,重头戏 RegisterNatives,这是一部宫廷史诗剧,精心的布局,宏大的场面。这么说吧,演员甲乙丙,就三个,共同出演一部不是你死就是我死的故事结局。剧本中记载了这么一段:

/**
 * 向JNI环境注册一个本地方法
 * @param clazz  包含本地方法的Java类
 * @param methods 本地方法描述数组
 * @param nMethods 本地方法个数
 * @return 成功返回0,否则注册失败
 */
jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);

不知不觉,后知后觉,一个注释完成了解析。简单点,说话的方式简单点。该配合你演出的我演视而不见。这个登记员的描述,大体如此了,如有更多需求,请自行研究。

三。结束 JNI_OnUnload 方法

出来混的迟早都是要还的,庞大的 JNI 帝国也有结束的那一天。当VM释放该组件时会调用 JNI_OnUnload 方法,曾经拥有的,比如说对象啊,通通在这里回归大地,化作春泥更护花。 当然也可以选择放弃,这个方法甩在一边,那么毒蘑菇总有一天会茁壮成长的,慢慢慢慢,然后boom。优化,是你我的一个可选项。

四。奇迹见证时刻

不得不说,这个时刻,我特别激动。花儿,为什么这么红?略微贴下代码,稍显细节:

static const char *jniClassName = "net/mapout/jni/JNILoader";
static JNINativeMethod methods[] = {
        {"sayHello", "()Ljava/lang/String;", (void*)jniSayHello},
};

static int registerNatives(JNIEnv* env) {
    jclass clazz = env->FindClass(jniClassName);
    if (clazz == NULL)
        return JNI_FALSE;

    jint methodSize = sizeof(methods) / sizeof(methods[0]);
    if ( env->RegisterNatives(clazz, methods, methodSize) < 0 )
        return JNI_FALSE;

    return JNI_TRUE;
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
        return JNI_ERR;

    //注册方法
    if (!registerNatives(env))
        return JNI_ERR;

    result = JNI_VERSION_1_6;
    return result;
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
    JNIEnv *env = nullptr;
    jint ret = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
    if (ret != JNI_OK) {
        return ;
    }
    //回收二手女朋友,回收... 嘿嘿嘿
}

一目了然,我们所需要维护的就是methods这个数组了,剩下的都是复制粘贴。稍微来个对比:

/**
 * 动态注册。命名简洁,清晰明了
 */
jstring jniSayHello(JNIEnv *env, jobject obj){
     return str2jstring( env, sayHello() );
}

/**
 * 静态注册。噗噗噗,一口老血喷涌而出
 */
JNIEXPORT jstring JNICALL Java_net_mapout_jni_JNILoader_sayHello
  (JNIEnv *env, jclass jclass){
    return str2jstring( env, sayHello() );
}

又是一个注释。代码,没有一个注释不能说清楚的,如果有,那就请用两个注释。说个细节,这里函数都有2个参数,一个 JNIEnv * 已经解释过了,还一个jobject。稍微讲一下,native方法如果没有static,那么就是类的实例,如果武装了static,进化加强,变为了类的class对象的实例。动态注册,就是这么回事,是时候展示实力的时候了。

动态注册项目结构图

附送一张机票,带你领略世界的浩瀚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容