前言
在上一篇文章中【JVM入门食用指南-03】JVM垃圾回收器以及性能调优[1],对垃圾回收器以及JVM性能调优进行了叙述,并对JVM中CMS垃圾回收器进行了重点阐述。通过之前在JVM中的铺垫,本文我们回到Android中,本文我们主要对 Android虚拟机和类加载机制进行叙述,加深对 Android 的理解。
即将学会
- ART 和 Dalvik
- Android 类加载流程
- 热修复实现原理
ART 与 Dalvik
JVM 与 DVM
JVM 是我们的 Java 虚拟机,而我们的Android应用运行在 Dalvik/ART 虚拟机上的。每一个应用对应一个 Dalvik 虚拟机,虽然 Dalvik 虚拟机也算 Java 虚拟机,不过执行的不是.class
文件,而是dex
文件。
这里对上述名词进行一些叙述
虚拟机分类
基于栈的虚拟机 每一个运行的线程,都有一个独立的栈,栈中记录了方法调用的历史,每一个方法的调用,都对应一个栈帧,并且将栈帧压入栈中,最顶部的栈帧为当前栈帧,既 当前执行的方法,基于栈帧 与 操作数栈进行所有操作。
寄存器 CPU的组成部分,寄存器是有限存储容量的高速存储容器(计算机中各级存储速度 寄存器-> 一级缓存->二级缓存 -> 内存 -> 硬盘),可以用来管理指令、数据的地址。
基于寄存器的虚拟机 (模拟寄存器的操作流程)
基于寄存器的虚拟机中没有操作数栈,不过有很多虚拟寄存器,类似操作数栈,这些寄存器也存放在运行时栈中,本质上就是一个数组,与JVM相似,在Dalvik 虚拟机中每个线程都有自己的PC 和 调用栈,方法调用的活动记录以帧为单位保存在调用栈上。
不同虚拟机流程
我们对比一下 基于栈的流程 和 基于寄存器的流程
JVM流程分析参考之前文章分析,通常需要经过以下操作
- 如将栈顶某类型值存入局部变量某处
- 将局部变量中某处某类型常量压入操作数栈
- 执行相关指令
DVM 中,直接依据指令,将某类型值存入虚拟寄存器中,相关的操作也依据指令在虚拟寄存器中通过CPU处理,将处理结果返回虚拟寄存器(省掉了基于栈的流程中局部变量与操作数栈中数据的流动)
ART 与 Dalvik 区别
ART 和 Dalvik 都是基于寄存器的虚拟机
Dalvik 执行 dex字节码,解释执行,在Android2.2 开始,支持即时编译,既选择程序中经常执行的代码(又称热点代码),进行编译和优化 减少了JVM中解释的流程。
ART虚拟机 (Android4.4) 直接跑机器码,不进行字节码解释。Android的运行时从Dalvik 无影响过渡ART,因为并不用开发者将应用直接编译成目标机器码,APk依旧是一个包含dex字节码的文件。
为什么APK依旧是包含dex字节码的文件,而ART和 Dalvik的执行方式不一样?
这里ART直接跑字节码,而Dalvik进行解释执行,并在2.2引入JIT,但是都是dex文件。
因为APK文件需要在Android系统中运行,需要进行安装,这个时候,经过虚拟机,会对dex进行优化,Dalvik中,会将dex字节码进行优化生成odex文件,而ART 会将 dex字节码翻译为本地机器码(引入了预先编译机制 Ahead of Time),安装时,ART使用设备自带的dex2oat工具对应用进行编译。dex中的字节码被编译成本地机器码,这也是为什么我们安装的时候比较慢。
不过后面从Android O
开始,安装速度变快了,因为这个时候采用混合编译了,JIT、AOT、和字节码解释。 当应用首次安装时,不进行AOT编译,运行过程中采用解释执行,并将程序中经常要执行的代码进行即时编译(JIT),并将JIT编译后的方法记录到Profile
配置文件,当设备闲置时,利用编译守护进程,依据Profile
文件对