NDK概览
2020-05-14 本文已影响0人
PanGeng
JNI
- 定义:Java Native Interface,即JAVA本地接口
- 作用:使JAVA语言和其他编程语言(C、C++等)进行交互
- JNI是JAVA调用NATIVE语言的一种特性
- 实际中驱动都是C和C<ins style="box-sizing: border-box;">开发的,通过JNI,JAVA可以调用C/C</ins>实现的驱动,从而扩展JAVA虚拟机的能力。另外,在高效率的数学运算、游戏的实时渲染、音视频的编码和解码等方面,一般都是用C开发的
为什么要有JNI
- 实际使用中,JAVA需要与本地代码进行交互
- 因为JAVA具备跨平台的特点,所以JAVA与本地代码交互能力非常弱
- 采用JNI特性,来增强JAVA与本地代码交互的能力
实现步骤(面试考点)
- 在Java中声明Native方法(即需要调用的本地方法)
- 编译上述JAVA源文件javac(得到.class文件)
- 通过javah命令导出JNI的头文件(.h文件)
- 使用JAVA需要交互的本地代码,实现在JAVA中声明的Native方法
- 编译.so库文件
- 通过JAVA命令执行JAVA程序,最终实现JAVA调用本地代码
NDK(C/C++)
- 定义:Native Development Kit,是android的一个开发工具包
- 作用:快速开发C、C++的动态库,并自动将so和应用一起打包成APK
- 提供了把.so和.apk打包的工具
- NDK提供的库有限,仅拥有算法效率和敏感问题
- 提供了交叉编译器,用于生成特定的CPU平台动态库
特点
- 运行效率高
- 代码安全性高
- 功能扩展性好
- 易于代码复用和移植
NDK和JNI的关系
- JNI是实现JAVA调用C/C++的途径,NDK是Android中实现JNI的手段
- 即在Android的开发环境中,通过NDK从而实现JNI功能
- JAVA的优点是跨平台,和操作系统之间的调用由JVM完成,但是一些和操作系统相关的操作就无法完成,JNI的出现刚刚弥补了这个缺陷,也完善了JAVA语言,将JAVA扩展的更强大
常用C/C++编译器
- clang
- 是一个C、C++、Object-C的轻量级编译器。基于LLVM(LLVM是以C++编写而成的构架编译器的框架系统,可以说是一个用于开发编译器的相关的库)
- gcc
- GNU C编译器。原本只能处理C语言,很快扩展,变得可以处理C++
- g++
- GUN C<ins style="box-sizing: border-box;">编译器,后缀为.c的源文件,gcc把它当作是C程序,而g</ins>当作是c<ins style="box-sizing: border-box;">程序;后缀为.cpp的,两者都会认为是c</ins>程序,g<ins style="box-sizing: border-box;">会自动链接c</ins>标准库stl,gcc不会,gcc不会定义__cplusplus宏,而g++会
- GDB(android默认使用此调试同居)
- 是一个由GUN开源组织发布的、UNIX/LINUX操作系统下的,基于命令 行的,功能强大的程序编译工具
C/C++编译过程
- 预处理
- 预处理阶段主要处理include和define等。它把#include包办进来的.h文件插入到#include所在的位置,把源程序中使用到的#define定义的宏用实际的字符串代替
- gcc -E main.c -o 文件.i, 执行以上命令即可进行预处理
- 编译
- 编译阶段,编译器检查代码的规范性、语法错误等,检查无误后,编译器把代码编译成汇编语言
- gcc -S 文件.i -o 文件.s, 执行以上命令将文件转成汇编语言
- 汇编
- 汇编阶段把.s文件翻译成二进制机器指令文件.o,这个阶段接受.c , .i .s 的文件都没有问题
- gcc -c 文件.s -o 文件.o, 将汇编编译成机器码执行
- 链接
- 链接阶段,链接的是区域的函数库,比如我们自己编写的c/c++文件中用到了三分的函数库,在连接阶段就需要链接三方函数库,如果链接不到就会报错
- gcc 文件.o -o 文件.exe ,打包成可执行文件
静态库(static library .a)android也可以使用
- 通常情况下,对函数库的连接是放在编译时期(compile time)完成的。所有相关的对象文件(objecct file)与牵涉到的函数库(library)被链接合成一个可执行文件(execuable file)。程序在 运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下。所以这些函数库被称为静态库(static library),通常文件名为“libxxx.a”的形式
动态链接库(dynamic link library .so)
- 把对一些库函数的链接载入推迟到程序运行时期(runtime)
- 可以实现进程之间的资源共享
- 将一些程序升级变得简单
- 甚至可以真正做到链接载入完全有程序员在程序代码中控制
交叉编译
- 本地编译
- 在当前便已平台下,编译出来的程序只能放到当前平台下运行,比如,我们在x86平台上,编写程序并编译成可执行程序。这种方式下,我们使用x86平台上的工具,开发针对x86平台本身的可执行程序,这个编译过程称为本地编译
- 交差编译
- 在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序,比如,我们在x86平台上,编写程序并编译成能运行在ARM平台的程序,编译得到的程序在x86平台上是不能运行的,必须放到ARM平台才能运行
交叉编译链
- 严格意义上来说,交叉编译器,只是指交叉编译的gcc, 但是实际上为了方便,我们常说的交叉编译器就是交叉工具链 [图片上传失败...(image-799a1f-1589443779287)]
交叉编译链的命名规则
- 我们使用交叉编译链时,常常会看到这样的名子:
- arm-none-linux-gnueabi-gcc
- arm-cortex_a8-linux-gnueabi-gcc
- mips-malta-linux-gnu-gcc
- 这些交叉编译链的命名似乎是通用的,有一定的规则
- arch-core-kernel-system
- arch: 用于哪个目标平台
- core: 使用的是哪个CPU Core,如Cortex A8,但是这一组命名好像比较领过,在其他厂家提供的交叉编译链中,有以厂家为名的,也有以开发版本命名的,或者直接是 none或者cross的。
- kernel: 所运行的OS,常见的有Linux, unlinux, bare(无os)。
- system: 交叉编译链所选择的库函数和目标映像的规范,如gnu, gnuabi等。其中gnu等价于glibc+oabi; gnueabi等价于glibc+eabi
应用二进制接口
