JNI原理(上)
一、编译
CPU只能识别0101这样的二进制文件,C/C++需要经过一层编译转成二进制文件。在Windows平台上会转成xxx.obj文件,在Linux平台会转成xxx.o文件。此由过程编译器完成。
编译规则:
- Eclipse ====> GUN ====> Android.mk
- Android Studio ====> LLVM ====> CMakeLists.txt
二、链接
在Windows平台上,obj链接生成.dll文件,Linux生成.so文件。链接会执行检查,如果失败则抛出Link error的异常。
注:在NDK开发过程中需要声明引入哪些.c/.cpp文件以及链接哪些.so库。
三、系统如何识别native方法
编写两个方法,其中一个为native方法
public static native void diff(String path, String patternPath, int fileNum);
public static void javaDiff(String path, String patternPath, int fileNum) {
}
使用javac
编译该类(如果使用Kotlin则用kotlinc
,需要到Github下载Kotlin编译器),获得一个.class文件,使用javap -v
反编译该class文件,可以看到
public static native void diff(java.lang.String, java.lang.String, int);
descriptor: (Ljava/lang/String;Ljava/lang/String;I)V
flags: ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
public static void javaDiff(java.lang.String, java.lang.String, int);
descriptor: (Ljava/lang/String;Ljava/lang/String;I)V
flags: ACC_PUBLIC, ACC_STATIC
native方法比普通方法多出一个 ACC_NATIVE 的标识
四、Native方法(动态链接库)什么时候加载到JVM里面
第一步,寻找链接库
由
loadLibrary(String libname)
方法进入,方法内部是调用了RunTime的 loadLibrary0
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), libname);
}
方法内ClassLoader会根据库名去寻找该库文件全路径
String filename = loader.findLibrary(libraryName);
继续进入 findLibrar