Android 进阶——NDK开发
来源:互联网 发布:城乡居民收入差距数据 编辑:程序博客网 时间:2024/06/05 11:17
NDK介绍
NDK(Native Development Kit)即本地代码开发套件,既然提到本地代码与之对应就有非本地代码。
众所周知Android系统是基于Linux进行改写而成,而Android程序是由Java代码进行编写,Java代码最大的优点在于其跨平台的特性,因此不能直接运行在操作系统之上,而是运行在自家的JVM
虚拟机中,Android程序也是这样,每一个Android程序都运行在一个独立的Dalvik虚拟机中。
由于这个机制当系统需要执行对应的Java代码时Dalvik虚拟机会进行一次解释,这样便导致了运行速率的降低。所以便引入了本地代码native
的概念,使用本地代码编写程序可以由操作系统直接执行,省去了中间虚拟机解释的过程,可以让应用运行的更快。而NDK就是Google公司开发的一套可以将C代码编译成本地代码的开发套件。- 使用NDK的好处
- 可以提高程序的执行效率。
- 常见的
.class
很容易被反编译,而C/C++库被反编译的难度较大。 - C语言的历史显然远远大于Java,因此市面上存在大量现成的C/C++库可以提供使用。
- C语言库支持各种硬件平台,因此编写C库可以方便在别的平台进行复用,例如嵌入式开发。
- 支持增量升级。
JNI
JNI(Java Native Interface)即Java本地接口,熟悉Java和面向对象的人都知道接口的含义,简而言之就是一种规则、规范。这里的JNI也是同样的道理。
在Android中编写本地代码需要使用C/C++进行编程,而如何定义Java和C两种不同语言的交互规则就是JNI的存在意义。可以将JNI看做一座桥梁,一座连通Java和C的桥梁,两种语言需要通过JNI这座桥才可以进行信息的交换。直接的体现就是通过JNI可以将Java的数据给C使用,同时C的数据也能给Java使用。
常见的例子:Java需要使用一串字符串时,有封装好的String
对象,而在C语言中是没有String这种概念的,字符串在C中只能通过*char[]
字符数组的指针进行操作,为了实现两种平台的交互,JNI中定义了jstring的类型。链接库
- 静态链接库
将所需要的一切依赖库都便已在一个文件中,体积大。后缀名.a - 动态链接库
运行时才去查找相关依赖库,体积小,但是可能出现找不到依赖库等问题。
- 静态链接库
交叉编译
在某个平台上生成另一个平台的可执行代码
例如:x86 -> Arm Arm->x86make
将指定的C文件编译成可执行的链接库
Android下本地开发基本流程
1.创建java类,声明需要使用的本地方法,用native
标识。
2. 通过JDK命令javah
生成本地方法对应的c头文件。
3. 编写JNI层,引入生成的头文件,并且实现其中的方法。
4. 编写CMakeLists.txt(老版本为Android.mk已经被cmake代替)文件,引入三方链接库,头文件,以及之间的关联关系。设置最终编译的链接库名字和类型。
5. 在Java代码中使用静态代码块引入,其中名字为make文件中设置的名字,不需要写后缀名。(最后生成的名字和设置的名字会有所不同,通常会在前面默认添加lib
)。
{System.loadLibrary("xxxx");}
写在最后
远在Android2.2之后Google便引入了JIT(Just In Time Compiler)编译系统。我们使用Java开发android,在编译打包APK文件时,会经过以下流程:
- Java编译器将应用中所有Java文件编译为class文件
- dx工具将应用编译输出的类文件转换为Dalvik字节码,即dex文件之后经过签名、对齐等操作变为APK文件。
Dalvik虚拟机可以看做是一个Java VM,他负责解释dex文件为机器码,如果我们不做处理的话,每次执行代码,都需要Dalvik将dex代码翻译为微处理器指令,然后交给系统处理,这样效率不高。
为了解决这个问题,Google在2.2版本添加了JIT编译器,当App运行时,每当遇到一个新类,JIT编译器就会对这个类进行编译,经过编译后的代码,会被优化成相当精简的本地代码(即native code),这样就避免了虚拟机解释的过程。
一直持续到Android4.4之后,Google公司提出了另外一套运行模式ART(Android Run Time)。
JIT编译方式虽然实现了每次运行程序只需要执行一次编译工作,但是依然运行在虚拟机上,编译工作是及时性进行的,也就是每次运行程序后都需要再次对代码进行编译。
ART的策略与Dalvik不同,在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。之后打开App的时候,不需要额外的翻译工作,直接使用本地机器码运行,因此运行速度提高。
通过ART和JIT,其实现在使用Java编写的Android程序相对于C已经不存在明显的劣势了,那为什么我们还要使用NDK开发呢。个人分析,有以下几点:
- 虽然从编译角度上说两者几乎已经没有区别,但是Java的特性决定了对于一些大量精密的逻辑操作远不如C来的简单粗暴,毕竟C中的静态内存是程序员自己分配和释放的,可以在使用代码使用完后的第一时间进行资源的释放,而Java则是依赖GC进行自动的垃圾回收,虽然GC的算法很强大,但是灵活性始终不如人工来的即时。
- C语言历史悠久,为了使用已有的解决方案无法避免的需要调用他人封装好的C库。
- 对于一些底层开发,如硬件层和协议层,C可以直接操作内存地址和CPU指令的特点无可替代。
因此我们需要理性分析,根据实际情况酌情使用NDK开发。并不是NDK效率就一定会高于原生Java开发。
- Android 进阶——NDK开发
- Android Ndk开发进阶
- Android进阶之NDK开发入门
- Android进阶之路——NDK(一)
- Android进阶之路——NDK(二)
- ndk系列——使用Android Studio 初探NDK开发
- Android NDK 开发进阶之 mk文件写法
- Android NDK开发——环境配置
- Android——NDK开发(一)
- Android——NDK开发(二)
- Android开发进阶—Android中的View
- Android的NDK开发(6)——如何定位Android NDK开发中遇到的错误
- android NDK 的进阶实验
- Android开发进阶——测试
- Android开发进阶——使用Dagger2
- Android开发高级进阶——传感器
- Android开发进阶—View的滑动
- Android逆向基础笔记—Android NDK开发4之Android studio NDK自动编译
- 更改mysql字符集utf8至utf8mb4
- 剪切板底层机制
- 反射面试专题
- 如何使用GIT上传自己的代码到码云(windows)
- Intellij插件
- Android 进阶——NDK开发
- 100道动态规划——38 HDU 5763 Another Meaning KMP + DP
- 程序员,如何从平庸走向理想?
- CENTOS7搭建HADOOP2.7.3集群
- 实现搜索框(含历史搜索记录)
- TextView加粗、删除线、下划线
- 2017第九届中国云计算大会早鸟票报名
- mysql_内部函数
- Angular---作用域与事件