JVM
传统的Java虚拟机,基于栈,运行class文件。
工作原理
编译与加载:
- 开发者编写的
.java
源文件被编译器(javac)转换为.class
文件(字节码)。 - JVM 的类加载器(ClassLoader)将
.class
文件加载到内存中。
解释执行:
- JVM 的执行引擎读取字节码,并将其解释为底层机器指令。
- 对于高频代码段,JIT 编译器会将字节码直接编译为机器码执行,避免解释的开销。
内存管理:
- JVM 为对象分配内存(通常在堆中)。
- 垃圾回收器(GC)定期回收不再使用的对象,释放内存空间。
编译策略
JIT(Just-In-Time)
即运行时编译策略,可以理解成一种运行时编译器,此时Andriod的虚拟机使用的是Dalivik,为了加快Dalvik虚拟机解释dex的速度,运行时动态地执行频率很高的dex字节翻译成本地机器码
缺点:
每次重启都需要重新编译
运行时比较耗电,造成电池额外开销
AOT(Ahead-Of-Time)
在应用安装时将 DEX 文件编译为本地机器码,存储在设备上。一种运行前编译的策略
缺点:
应用安装和升级之后的应用优化比较耗时
优化后的文件会占用额外的存储空间
两者区别
IT是在运行时进行编译,是动态编译,并目每次运行程序的时候都需要对odex重新进行编译
AOT是静态编译,应用在安装的时候会启动dex2oat过程把dex预编译成ELF文件,每次运行程序的时候不用重新编译,是真正意义上的本地应用
Android7.0后安装时不会编译、运行时热点函数jit编译、休息时采用AoT预编译
Dalvik虚拟机
早期的 Android 系统采用的是 Dalvik 虚拟机,由 Google 开发,支持已转换成dez格式的安卓应用,执行指令更快,加载的是odex(优化的dex)
基于寄存器的架构:相比传统 Java 虚拟机(JVM)的基于堆栈架构,Dalvik 使用寄存器架构,能够更高效地执行指令。
DEX 格式:Dalvik 不直接运行 Java 字节码,而是运行通过 dx
工具转换后的 .dex
(Dalvik Executable)格式文件。这种格式针对内存占用进行了优化。
多实例:Dalvik 为每个应用分配独立的虚拟机实例,隔离不同应用的运行环境,增强了安全性。
Dalvik 的工作原理
- 编译流程:Java 源代码 → 编译成
.class
文件(Java 字节码) → 转换为.dex
文件。 - 加载和执行:
- 应用启动时,Dalvik 将
.dex
文件加载到内存,并解释执行其中的字节码。 - Dalvik VM 通过 JIT(Just-In-Time)编译器在运行时将部分字节码动态编译为机器码,以提升性能。
- 应用启动时,Dalvik 将
ART虚拟机
从 Android 5.0(Lollipop)开始,ART 替代 Dalvik 成为默认的运行时环境。
提前编译(AOT,Ahead of Time):在应用安装时,ART 将字节码编译为机器码,避免运行时编译,从而提高性能。
内存效率:ART 在垃圾回收和内存分配上进行了优化,更适合现代智能手机。
向后兼容:ART 仍然支持运行 Dalvik 的 DEX 文件,同时对现有应用提供兼容。
ART 的工作原理
- 安装时编译:应用安装过程中,ART 使用 AOT 编译器将 DEX 文件直接转换为机器码,生成可执行oat文件(ELF文件),存储在设备的
/data
分区中。 - 运行时:
- ART 直接执行预编译的机器码,避免了 JIT 的实时编译开销。
- ART 支持垃圾回收(GC),减少内存碎片,提高应用响应速度。