了解安卓虚拟机:ART和DVM

QuibblerQuibbler 2020-08-08 约 11 分钟 2452 次阅读

了解安卓虚拟机:ART和DVM

Android每个APP都运行在相互独立的虚拟机中,不会因为一个应用的奔溃引起其它正在运行的应用也奔溃。Android虚拟机和Java虚拟机有千丝万缕的联系,Android发展史上一共出现过两种虚拟机:DVM和ART。虚拟机的实现非常复杂,不亚于一个小型OS。不需要刨根问底了解虚拟机实现的每一个细节,但是应用开发需要对底层的虚拟机有一个基本的了解。

Android虚拟机在系统架构中的位置,仅次于Frameworks层之下。参考: 平台架构">Android 开发者 > 平台架构

1、Android和Java虚拟机

安卓虚拟机和Java虚拟机有千丝万缕的联系,但是两者又有很多不同。安卓系统一般运行在便携设备上,性能无法与PC相比,所以安卓虚拟机对架构进行了调整,以此适应性能较低的移动设备。安卓虚拟机并不是JVM,因为它没有遵循JVM规范。

两者的执行文件不同,Android虚拟机最终执行的是APK中的.dex文件。

Java虚拟机:.java -> .class -> .jar -> JVM

Android虚拟机:.java -> .class -> .dex -> ART/DVM

2、DVM

Dalvik虚拟机(Dalvik Virtual Machine)是Google专门为Android编写的虚拟机,Dalvik Virtual Machine的作者是丹伯恩斯坦(Dan Bornstein),Dalvik一词来源于他祖先的故乡。

2.1、历史

随Android诞生,在Android 2.2上DVM开始采用JIT及时编译。直到Android 5.0开始系统默认使用ART虚拟机,DVM才完全退出历史。

2.2、源码

DVM源码可以在AOSP开源项目中查看,在/dalvik 目录下。下面列出部分目录:

        docs:文档

        dexgen:-

        tools:DVM工具

        libdex:dex相关的库

        dx:dx工具,将java转成dex

        dexdump:dex反汇编

        opcode-gen:已定义的操作码和Dalvik的指令格式

2.3、堆

DVM运行时堆主要由两部分:Zygote Space和Allocation Space组成。

2.4、垃圾回收

DVM采用的是标记-清除(Mark-Sweep)垃圾回收算法进行GC。

2.5、日志

虚拟机GC额的日志可以通过logcat查看,DVM的GC日志格式如下:(找不到DVM的机器抓取log就不演示了)

<GC原因><释放的对象数量>(释放内存大小)<释放的大对象数量>(释放大对象内存大小) <堆的空闲百分比><已用内存><总内存><暂停时长>

3、ART

ART(Android Runtime)虚拟机是Android 4.4 发布的,替换DVM虚拟机,但是Android 4.4默认采用的还是DVM。从Android 5.0开始默认采用ART,DVM被彻底淘汰。详细ART虚拟机说明参考: 平台 > Android Runtime">Android 开发者 > 平台 > Android Runtime

        对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART 编写为通过执行 DEX 文件在低内存设备上运行多个虚拟机,DEX 文件是一种专为 Android 设计的字节码格式,经过优化,使用的内存很少。编译工具链(例如 Jack)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。

3.1、历史

在Android 4.4的时候推出,替代DVM。从Android 5.0开始成为安卓系统默认的虚拟机,至今。

3.2、源码

ART源码也随着AOSP一起开源,ART虚拟机源码在/art 目录下。有如下目录:

        benchmark/  compiler/  dexdump/    disassembler/  profman/  sigchainlib/  cmdline/    dex2oat/   dexlayout/  libart_fake/   patchoat/  runtime/  test/  tools/

3.3、堆

ART运行时堆主要由四部分组成:Zygote Space、Allocation Space、Image Space、Large Object Space。前两个和DVM堆作用一样,Image Space堆空间用来存放预加载类,Large Object Space堆用来分配给大对象(12kb)。

另外,Zygote Space和Image Space是进程间共享的,这样一个应用加载过的类,其它应用无需重复加载,提高移动设备的内存利用率和运行效率。

3.4、垃圾回收

DVM只采用了标记-清除这一种垃圾回收算法,ART采用了多种垃圾回收算法进行改进:

①Concurrent Mark Sweep(CMS):CMS收集器采用了标记-清除算法实现

②Concurrent Partial Mark Sweep:部分完整的堆垃圾收集器

③Concurrent Sticky Mark Sweep:粘性收集器,基于分代垃圾收集思想

④Marksweep + Semispace:非并发的GC

3.5、log

虚拟机GC额的日志可以通过logcat查看,ART的GC日志格式如下:

<GC原因><垃圾回收器名><释放的对象数量>(释放内存大小)<释放的大对象数量>(释放大对象内存大小) <堆的空闲百分比><已用内存><总内存><暂停时长><GC总耗时>

抓取几个gc日志查看:

I/m.huawei.iawar: Explicit concurrent copying GC freed 18772(1096KB) AllocSpace objects, 11(220KB) LOS objects, 61% free, 3788KB/9932KB, paused 93us total 54.002ms

I/maple:  NaiveRC GC for force: async:collected objects: 0(0B), 91.1665% utilization (3MiB/3MiB), max pause: 217us, total pause: 351us, total GC time: 26ms

4、JIT和AOT

安卓虚拟机有两种编译方式:JIT(Just In Time Compiler,即时编译器)和AOT(Ahead Of Time Compiler,预编译)。

4.1、JIT

JIT(Just In Time Compiler),即时编译器。每次安卓虚拟机执行dex文件,都需要先将dex字节码转成机器码,然后由系统执行,很明显这样APP运行效率比较低。于是Android 2.2 DVM就加入了JIT,对多次运行的热点代码进行编译生成机器码,这样对于经常执行的代码速度就比较快。

但是每次应用关闭再打开需要重写进行JIT,预编译的机器码并非持久的。

4.2、AOT

AOT(Ahead Of Time Compiler),预编译。在ART虚拟机中加入了AOT编译方式:将应用字节码全部转换为机器码,这样在运行的时候就直接运行机器码,效率非常高。

但是AOT又有另外几个缺点:应用在安装的时候进行一次AOT,这样的话应用的安装时间就会变慢;其次,字节码转换成机器码占用的存储个多。

Android 7.0 又采用了AOT和JIT混合编译方式:安装的时候并不将字节码转成机器码,在运行的时候将经常运行的字节码转成机器码保存起来。这样安装的时间不会增加,而且后面执行的速度会变快。

5、DVM和ART的区别

DVM和ART的区别有如下,总的来说就是好的淘汰旧的。

①DVM较旧只支持32位CPU,ART支持64位CPU还兼容32位CPU

②DVM只有一种垃圾回收算法,而ART支持多种垃圾回收算器。

③DVM先没有JIT,后来加入JIT。ART先有AOT,后来又加入JIT。

④ART和DVM的堆不同,前面提到。

参考资料:

        在 Android Runtime (ART) 中验证应用行为

        JVM、DVM、ART的区别

Jvm、Dalvik和Art的区别

       Android 各类虚拟机JVM,DVM,ART区别

       Android内存优化DVM和ART原理初探

       简单聊聊JVM,DVM,ART

       扒一扒 Android 运行时: DVM vs ART

       Android内存优化DVM和ART原理初探

      深入理解Java虚拟机——JVM、DVM(dalvik)和ART之间的区别

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w