前言
ART 虚拟机执行 Java 方法主要有两种模式:quick code 模式和 Interpreter 模式
- quick code 模式:执行 arm 汇编指令
- Interpreter 模式:由解释器解释执行 Dalvik 字节码
在之前的文章 ART 虚拟机 — Interpreter 模式 中详细介绍了 Interpreter 模式,因此本篇文章将代入一些例子,来帮助大家更好的理解 quick code 模式和 Interpreter 模式
一、art 虚拟机
在介绍这两种模式之前,我们先大体介绍一下 art 虚拟机
1.1 什么是虚拟机?
Virtual Machine:
- Run program like a physical machine
- Implemented by software
Functional classification:
- Run an Operate System (VirtualBox, VMWare)
- Only support for single process execution
根据上面的定义和分类,我们可以确定 art 虚拟机和 Jvm 虚拟机类似,都属于第二种,仅支持单一进程的运行;对于 single process 可以这样理解,在 Android 中,每个 Java 进程都有自己的虚拟机实例,换言之,每个虚拟机实例上面只运行着一个 Java 进程
1.2 与 Jvm 虚拟机的区别
每个 Java 类经过 javac 的编译都会生成对应的 class 文件,这些 class 文件便可以在 Jvm 虚拟机上运行;但是在 Android 中同一个 apk 的 class 文件会被 dx 工具打包为一个 dex 文件(某些情况下可能是多个),dex 文件经过 dex2oat 会生成对应的 oat 文件,art 虚拟机运行的就是这些 oat 文件
1.3 与 dalvik 虚拟机的区别
这张图应该是开发者文档中的一张图,很好的表现出了 art 虚拟机和 dalvik 虚拟机的区别,可以看到它们最主要的区别是对 Dex File 所作的处理不同:
- dalvik 虚拟机会通过 dexopt 处理 Dex File 生成 Odex 文件
- art 虚拟机会通过 dex2oat 处理 Dex File 生成 Oat 文件,图中的 ELF 是 Linux 上可执行文件的一种格式,Oat 文件也是一种 ELF 文件;dex2oat 会将 dex 字节码编译为机器可以直接运行的汇编指令,除此之外,Oat 文件当中还会包含原来的 Dex 文件
1.4 启动时机
(本篇文章暂时不对 Zygote 和 Zygote64 作区分)
我们知道 Zygote 进程是第一个 Java 进程,其是 init 通过加载 init.rc 来启动的,图片里第一个框中的内容是 init.zygote64_32.rc 中的, 表示定义一个名为 zygote 的 service,它的启动入口是 /system/bin/app_process64,后面是传入的一些参数。在 app_process/app_main.cpp 中,系统会去启动 runtime,runtime 启动时会启动虚拟机并且调用 ZygoteInit 类的 static void main(String[] args) 方法,这也是被调用的第一个 Java 方法
二、ArtMethod
(基于 Android 8.1)
想要理解 Java 方法在虚拟机中的执行,肯定绕不开 art::ArtMethod 这个类,在 Android 中,每个 Java 方法(包括 native 方法)都对应一个 art::ArtMethod 对象,一个 art::ArtMethod 对象描述一个 Java 方法,art::ArtMethod 的结构如下所示:
(gdb) ptype 'art::ArtMethod'
type = class art::ArtMethod {
public:
static const bool kCheckDeclaringClassState;
static const uint32_t kRuntimeMethodDexMethodIndex;
protected:
art::GcRoot<art::mirror::Class> declaring_class_;
std::__1::atomic<unsigned int> access_flags_;
uint32_t dex_code_item_offset_;
uint32_t dex_method_index_;
uint16_t method_index_;
uint16_t hotness_count_;
art::ArtMethod::PtrSizedFields ptr_sized_fields_;
}
(gdb) ptype 'art::ArtMethod::PtrSizedFields'
type = struct art::ArtMethod::PtrSizedFields {
art::mirror::MethodDexCacheType *dex_cache_resolved_methods_;
void *data_;
void *entry_point_from_quick_