一. JNI介绍
- JNI引入
JNI概念 : Java本地接口,Java Native Interface, 它是一个协议, 该协议用来沟通Java代码和外部的本地C/C++代码, 通过该协议 Java代码可以调用外部的本地代码, 外部的C/C++ 代码可以调用Java代码;
C和Java的侧重 :
– C语言 : C语言中最重要的是 函数 function;
– Java语言 : Java中最重要的是 JVM, class类, 以及class中的方法;
C与Java如何交流 :
– JNI规范 : C语言与Java语言交流需要一个适配器, 中间件, 即 JNI, JNI提供了一种规范;
– C语言中调用Java方法 : 可以让我们在C代码中找到Java代码class中的方法, 并且调用该方法;
– Java语言中调用C语言方法 : 同时也可以在Java代码中, 将一个C语言的方法映射到Java的某个方法上;
– JNI桥梁作用 : JNI提供了一个桥梁, 打通了C语言和Java语言之间的障碍;
JNI中的一些概念 :
– native : Java语言中修饰本地方法的修饰符, 被该修饰符修饰的方法没有方法体;
– Native方法 : 在Java语言中被native关键字修饰的方法是Native方法;
– JNI层 : Java声明Native方法的部分;
– JNI函数 : JNIEnv提供的函数, 这些函数在jni.h中进行定义;
– JNI方法 : Native方法对应的JNI层实现的 C/C++方法, 即在jni目录中实现的那些C语言代码;
2 Android中的应用程序框架
正常情况下的Android框架 : 最顶层是Android的应用程序代码, 上层的应用层 和 应用框架层 主要是Java代码, 中间有一层的Framework框架层代码是 C/C++代码, 通过Framework进行系统调用, 调用底层的库 和linux 内核;
使用JNI时的Android框架 : 绕过Framework提供的调用底层的代码, 直接调用自己写的C代码, 该代码最终会编译成为一个库, 这个库通过JNI提供的一个Stable的ABI 调用linux kernel;ABI是二进制程序接口 application binary interface.
纽带 : JNI是连接框架层 (Framework - C/C++) 和应用框架层(Application Framework - Java)的纽带;
JNI在Android中作用 : JNI可以调用本地代码库(即C/C++代码), 并通过 Dalvik虚拟机 与应用层 和 应用框架层进行交互, Android中JNI代码主要位于应用层 和 应用框架层;
– 应用层 : 该层是由JNI开发, 主要使用标准JNI编程模型;
– 应用框架层 : 使用的是Android中自定义的一套JNI编程模型, 该自定义的JNI编程模型弥补了标准JNI编程模型的不足;
Android中JNI源码位置 : 在应用框架层中, 主要的JNI代码位于 framework/base目录下, 这些模块被编译成共享库之后放在 /system/lib 目录下;
NDK与JNI区别 :
– NDK: NDK是Google开发的一套开发和编译工具集, 主要用于Android的JNI开发;
– JNI : JNI是一套编程接口, 用来实现Java代码与本地的C/C++代码进行交互;
**JNI编程步骤:
– 声明native方法 : 在Java代码中声明 native method()方法;
– 实现JNI的C/C++方法 : 在JNI层实现Java中声明的native方法, 这里使用javah工具生成带方法签名的头文件, 该JNI层的C/C++代码将被编译成动态库;
– 加载动态库 : 在Java代码中的静态代码块中加载JNI编译后的动态共享库;**
3 . JNI作用
JNI作用 :
– 扩展: JNI扩展了JVM能力, 驱动开发, 例如开发一个wifi驱动, 可以将手机设置为无限路由;
– 高效 : 本地代码效率高, 游戏渲染, 音频视频处理等方面使用JNI调用本地代码, C语言可以灵活操作内存;
– 复用 : 在文件压缩算法 7zip开源代码库, 机器视觉 openCV开放算法库 等方面可以复用C平台上的代码, 不必在开发一套完整的Java体系, 避免重复发明轮子;
– 特殊 : 产品的核心技术一般也采用JNI开发, 不易破解;
Java语言执行流程 :
– 编译字节码 : Java编译器编译 .java源文件, 获得.class 字节码文件;
– 装载类库 : 使用类装载器装载平台上的Java类库, 并进行字节码验证;
– Java虚拟机 : 将字节码加入到JVM中, Java解释器 和 即时编译器 同时处理字节码文件, 将处理后的结果放入运行时系统;
– 调用JVM所在平台类库 : JVM处理字节码后, 转换成相应平台的操作, 调用本平台底层类库进行相关处理;
二. NDK详解
- 交叉编译库文件
C代码执行 : C代码被编译成库文件之后, 才能执行, 库文件分为动态库 和静态库 两种;
– 动态库 : unix环境下.so 后缀的是动态库, windows环境下.dll 后缀的是动态库; 动态库可以依赖静态库加载一些可执行的C代码;
– 静态库 :.a 后缀是静态库的扩展名;
库文件来源 : C代码 进行 编译 链接操作之后, 才会生成库文件, 不同类型的CPU 操作系统 生成的库文件是不一样;
– CPU分类 : arm结构, 嵌入式设备处理器; x86结构, pc 服务器处理器; 不同的CPU指令集不同;
– 交叉编译 :windows x86编译出来的库文件可以在arm平台运行的代码;
– 交叉编译工具链 : Google提供的 NDK 就是交叉编译工具链, 可以在linux环境下编译出在arn平台下执行的二进制库文件;
NDK作用 : 是Google提供了交叉编译工具链, 能够在linux平台编译出在arm平台下执行的二进制库文件;
NDK版本介绍 : android-ndk-windows 是在windows系统中的cygwin使用的, android-ndk-linux 是在linux下使用的;