jni函数的注册流程

JNI函数的注册方式有两种,分别是静态注册与动态注册,对应的代码如下:

静态注册:
在这里插入图片描述

静态注册的方法名是以Java_开头的。

动态注册:
在这里插入图片描述

动态注册是通过调用RegisterNatives方法进行注册的。

静态注册

理解这两种注册方式的注册流程是学习vmp的前提,下面首先分析静态注册的流程。

在这里插入图片描述

在加载类的时候首先获取类的信息,如果拥有属性和方法,则调用LoadClassMembers进行类的加载

在这里插入图片描述

LoadClassMembers方法的前面部分是静态属性和实例属性的加载,后面是实例方法和静态方法的加载,上图我只贴了方法的加载。从源码中可以看到方法的加载有两步————LoadMethod、LinkCode

在这里插入图片描述

loadMethod是对参数中的ArtMethod实例对象进行初始化

在这里插入图片描述

LinkCode的前半段判断了是不是oat编译后的类以及需不需要解释器解释执行,由于加固厂商通常情况下阻断了dex编译成oat,因此ShouldUseInterpreterEntrypoint方法的返回值应该为true

在这里插入图片描述

当方法为native方法时,则调用UnregisterNative()进行第一次的注册,不管是静态注册还是动态注册都会调用这个方法,两种注册方法的不同主要在第二次注册上,先不多说,进入到该方法中看看

在这里插入图片描述

代码很简单,把GetJniDlsymLookupStub()的返回值设置为入口,那重点时GetJniDlsymLookupStub()的返回值是什么

在这里插入图片描述

返回了art_jni_dlsym_lookup_stub函数指针指向的地址,我们来看看这个函数是什么

在这里插入图片描述

可以看到这个函数是用汇编写的,打开arm 32位的代码看一下

在这里插入图片描述

该汇编方法调用了artFindNativeMethod方法,跟进去看一下

在这里插入图片描述

由注释可以看出FindCodeForNativeMethod方法返回的是方法的地址,并通过RegisterNative方法进行第二次注册,这就是静态注册的整个流程。

如果继续跟进FindCodeForNativeMethod方法就会找到静态注册以Java_开头的原因,下面贴出关键代码,感兴趣的读者可以自行研究。

在这里插入图片描述

动态注册

对于动态注册来说,第一次注册于静态注册的第一次注册位置是一样的,都是UnregisterNative()方法,动态注册的第二次注册则由程序员编写完成,主要通过在JNI_OnLoad方法中调用RegisterNatives方法进行注册,下面跟进RegisterNatives方法的实现

在这里插入图片描述

在这里插入图片描述

该方法遍历methods数组,该数组的成员是JNINativeMethod结构体,获取其对应java中的名字、签名信息与具体实现的函数指针

在这里插入图片描述

最后每一个method都是用RegisterNative进行注册,至此动态注册的流程就完成了。

总结

静态注册与动态注册的第一次注册都是调用UnregisterNative()方法实现的,静态注册的第二次注册是调用了RegisterNative方法,而动态注册的第二次注册是由程序员主动调用的RegisterNatives方法把methods数组中的所有方法进行注册,但最终也是调用RegisterNative方法进行注册的。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值