Native方法
安卓的底层是Linux实现,但实际上程序入口是在Dalvik虚拟机中,作为字节码和运行在虚拟机中的代码本身就不具备太强的安全性,另一方面虚拟机的执行效率也是众所周知的
因此安卓允许通过so库的加载来调用底层linux执行代码,这就是Native方法
具体使用方法为在java层中使用System.loadlibrary(“test”),虚拟机会去载入libtest.so文件,同时去产生一个Load事件,这个事件触发后程序会去查找并执行JNI_OnLoad函数。相对的也存在一个UnLoad事件,触发JNI_OnUnLoad函数。
不过这个函数并不是强制要求的,用户也可以不去实现。它只是用来执行初始化和善后工作。相当于DLL_Main、构造函数一类的。
用户在so中编写的函数名必须为Java_类名_方法名
的样式,才能在java中调用。Dalvik会在函数列表中查找该函数来执行
但是这样一方面会使得函数过于明显,另一方面每次调用函数Dalvik虚拟机都会去函数列表中查找函数进行调用,导致效率被极大影响
对应的解决方案就是显式注册,将Native方法挂载到一个函数链表中,虚拟机会优先查找该列表,查找不到时才会再去函数列表
显式注册会使得Native方法不会在函数列表中出现,而是作为结构体中的函数指针
不过对于熟手而言,当函数列表中找不到方法时自然而然会去想到寻找显式注册的JNI方法,因此用处并不是很大
混淆
Native中可以通过JNI指针调用java层的方法,并且静态反编译器都是将java层和native层分开处理的,这样使得native调用的函数没法被交叉引用捕捉到
因此对于代码量较大的程序,可以使用java层->native函数->java层的方法来调用,使得静态分析受到很大的阻力