作者:FloatingGuy 转载请注明出处:https://floatingguy.github.io/


学习老罗的文章,简单记录一下
Android运行时ART简要介绍和学习计划

Dalvik

JIT (just in time)执行本地机器指令
尽管Dalvik也会对频繁执行的代码进行JIT生成本地机器指令来执行,但毕竟在应用程序运行的过程中将Dex字节码翻译成本地机器指令也会影响到应用程序本身的执行,因此即使Dalvik使用了JIT,也在一定程度上也比不上直接就可以执行本地机器指令的运行时。

ART

Java 虚拟机接口 + 垃圾回收

APK 安装时走 AOT 流程
AOT(Ahead of Time)相对 Jit而言。AOT 要求 apk 安装时就要编译成本地机器指令。

LLVM

在ART中,打包在APK里面的Dex字节码是通过LLVM翻译成本地机器指令的。LLVM是一个用来快速开发自己的编译器的框架系统。

基于LLVM架构开发的编译器的执行过程如图2所示

LLVM.png

  • 前端工具:对输入的源代码(Source Code)进行语法分析后,生成一棵抽象语法树(Abstract Syntax Tree,AST),并且可以进一步将得到的抽象语法树转化一种称为LLVM IR的中间语言。LLVM IR是一种与编程语言无关的中间语言

  • 优化器:优化器对LLVM IR文件进行优化,例如消除代码里面的冗余计算

  • 后端工具:后端负责生成最终的机器指令。

LLVM.png

dalvik 优化 dex 到 odex

APK在安装的时候,安装服务PackageManagerService会通过守护进程installd调用一个工具dexopt对打包在APK里面包含有Dex字节码的classes.dex进行优化,优化得到的文件保存在/data/dalvik-cache目录中,并且以.odex为后缀名,表示这是一个优化过的Dex文件。

art 优化 dex 到本地机器指令 (还保存为以前的 odex 文件)

在ART运行时中,APK在安装的时候,同样安装服务PackageManagerService会通过守护进程installd调用另外一个工具dex2oat对打包在APK里面包含有Dex字节码进翻译。这个翻译器实际上就是基于LLVM架构实现的一个编译器,它的前端是一个Dex语法分析器。翻译后得到的是一个ELF格式的oat文件,这个oat文件同样是以.odex后缀结束,并且也是保存在/data/dalvik-cache目录中。

oat 文件格式

oat 比正常的 ELF 可执行文件多了 oatdata 和 oatexec段。

  • oatdata 段 保存apk 中原始的 dex 文件
  • oatexec 段 保存翻译过后的 机器指令

图4 ART翻译classes.dex后得到的ELF格式的oat文件

后续内容:
ART加载oat文件的过程。
ART查找类和方法的过程。
ART查找类方法的本地机器指令的过程。
Dalvik虚拟机的垃圾收集过程。
ART的垃圾收集过程。

Android ART运行时无缝替换Dalvik虚拟机的过程分析

本文主要 结合源代码分析 art 替换 dalvik 需要做的工作。
总结下来就2部分:

  • 创建虚拟机 ART 虚拟机
  • 将dex 翻译成 oat 的过程

创建虚拟机 ART 虚拟机

这个过程要从 系统启动开始。

回忆一下 dalvik 虚拟的创建过程,是由 Zygote 进程完成,之后的所有进程都是从 zygote 孵化而来。

将dex 翻译成 oat 的过程

  • 在安装 apk 时会进行一次对待安装 app 的翻译
  • 在系统启动时,会对 /system/app 、/data/app、/system/framework 目录下的 apk 或者 jar 文件,以及这些 APK 所引用的外部 JAR,进行 dex 到 oat 的翻译。

上述2条翻译的路线都是从 PMS 开始,最后一直到生成 odex文件结束。