Xposed框架核心思想在于将java层普通函数注册成本地JNI方法,以此来变相实现hook机制(放在文章开头的话很重要哦,记住!)。
Xposed框架的技术核心建立在Jvm原生的JNI机制之上,为了对Xposed框架进行深入分析,同时方便大家理解,我们从以下三个问题着手:
1.Dalvik虚拟机在执行java层代码时如何识别JNI方法?
先来了解一下类的加载过程:当一个类第一次被使用到时,这个类的字节码会被加载到内存,并且只会回载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的list,这些方法描述符包含这样一些信息:
(1)方法代码存于何处,
(2)它有哪些参数,
(3)方法的描述符(public、native之类), etc...
如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。下面来看看方法描述符的样子。
注意:方法描述符实际上是一个结构体!
主要到上面的accessFlags了吗,它标记着该方法的类型,public、native等等,所以,要是想把一个方法注册成本地方法,这个标记是必须要改的!
我们知道了accessFlags的作用还不够的,最好还是再了解一下它在执行过程中是怎么发挥作用的,追本溯源吗!
这里简要的描述一下Dalvik虚拟机执行代码基本过程:
一个类在执行之前先会被装载,之后要进行字节码验证(dvmVerifyCodeFlow(),感兴趣的去查查源码),检验完成之后虚拟机会紧接着调用FindClass()来查找并装载main的方法类。此后JNIEnv类调用成员函数CallStaticVoidMethod执行main方法,程序开始运行。来看下面这张函数调用流程图。
找到应用的入口函数(main),依次调用执行。
最终会调用到dvmCallMethodV这个方法,下面是这个方法的实现。
调用了一个关键的函数dvmIsNativeMethod,这个方法的作用就是判断函数的类型,通过比对方法描述符中的accessFlags与ACC_NATIVE(常量)是否相等来识别该方法是否是NATIVE方法。如下图。