Android App主要采用Java编程语言编写,包括Activity、Service、Broadcast Receiver、ContentProvider 四大组件。Android App的编译过程与一般的Java App 不同,但开始方式是一样的:使用javac命令将java源代码文件编译成class文件,如图所示:
首先创建一个Test.java测试程序,然后使用javac Test.java命令将Test.java源代码生成Test.class文件:
然后,使用javap -c Test.class命令查看上面的Java代码对应的Java字节码:
Android系统App并不是使用标准的Java虚拟机来运行,而是通过自带的Dalvik虚拟机来运行。与Java虚拟机的字节码不同,Dalvik虚拟机有自己独特的字节码格式,即两个虚拟机的机器指令集不同,因此通过javac 编译生成的class文件也就无法在Dalvik虚拟机上运行。
开发者需要使用Android系统的dx命令(位于/Users/tale/Library/Android/sdk/build-tools/29.0.2/路径下),将class文件和所有的jar包转换成符合Dalvik字节码格式的classes.dex 文件,如图下图所示。 命令格式: dx --dex --output=classes.dex Test.class若无法执行dx命令,需添加环境变量: export PATH=$PATH:/Users/tale/Library/Android/sdk/build-tools/29.0.2使用dexdump命令去查看classes.dex文件对应的Dalvik 字节码形式如下:
classes.dex文件为Android App的可执行文件,核心代码都在这个文件中。为了便于安装,Android将App打包成类似于zip压缩文件的apk文件。apk文件不仅包含App的所有代码,而且还包含所有的非代码资源,如图片、声音等。使用Andorid SDK中的打包工具或者Android系统的aapt命令,就能将classes.dex文件和App涉及的资源文件(如图片文件和布局配置描述文件等)打包成apk文件,即Android安装包文件。
第三方应用商店向用户发布App安装文件之前,Android系统要求开发者对App文件进行数字签名:一方面出于对App负责,实现App的可溯源;另一方面便于操作系统在App安装时利用数字签名校验安装文件的完整性和准确性,实现App的防篡改。对App包进行签名的过程是,使用开发者的私钥对apk安装文件包中的所有文件进行校验,并将生成的校验信息作为一个附加的签名文件内置于apk文件包中。
jarsigner是Java开发工具包中常用的签名工具,专门为jar文件进行签名而创建,也可以用于对apk文件进行签名。
zipalign是压缩文件对齐工具,确保apk文件的压缩部分在字节边界上是对齐的,这样就可以在不解压文件的情况下读取其中的内容。 1.2 Android App的运行在Android 4.4 版本后,在原有以Dalvik虚拟机方式运行App的基础上,新增了ART模式。Dalvik虚拟机运行时模式下,App每次运行都需要通过即时编译器将dex文件字节码转换为机器码,即App的每次运行都是转换加运行,虽然这会加快安装过程,但是会拖慢每次启动运行的效率。而在ART模式下,App在第一次安装的时候,就会进行预编译,将字节码编译成机器码。这么做虽然会使设备和App的安装与首次启动变慢,但在此后的每次启动运行,App都省去了机器码转换的工作,提高了运行效率。
图一、Java虚拟机整体流程
图二、Dalvik虚拟机整体流程
图三、ART虚拟机整体流程
App在ART模式下运行的过程:
在Android 系统中,一个名为Zygote 的进程用来孵化和启动其他App,这也是Android 运行的第一个Dalvik 虚拟机进程。Zygote进程通过调用系统fork()函数来快速创建自身的副本进程。Android 系统是基于Linux内核的,通过fork调用可以在短时间内复制生成一个Zygote 副本进程。
之所以通过Zygote 进程复制新的进程,是因为复制像Zygote 这样的半启动进程比从主系统文件中加载新进程要快得多。也就是说,通过Zygote 进程复制可以使App 的启动速度更快。
在ART模式下,Android系统使用dex2oat 命令将classes.dex 文件中的字节码转换为本地oat 格式文件。
oat格式文件是一种Android 系统自有的elf文件格式,它不仅包含classes.dex 文件内容,而且还包含由classes.dex 文件转换的机器指令。因此系统在App 每次运行时重新转换原有classes.dex 文件中的机器指令,就可以使用oat 文件中已经转换好的机器指令在ART 模式下直接运行App。
系统将oat文件和相关库文件加载到内存中,并且直接映射到App 进程的内存区域,App的初始化从这里开始,之后App将出现在屏幕上。
|