Android VM

知识点、在这里插入图片描述

一、安卓虚拟机的发展历史

1、诞生

每次运行程序的时,Dalvik VM负责加载 dex/odex 文件并解析成机器码交由系统调用。

2、Android 2.2 JIT 登场

和其他大多数 JVM 一样,Dalvik 使用 JIT 进行即时编译,借助 Java HotSpot VM,JIT 编译器可以对热点代码进行编译优化,将 dex/odex 中的 Dalvik Code ( Smali 指令集 ) 翻译成相当精简的 Native Code 去执行,JIT 的引入使得 Dalvik 的性能提升了 3~6 倍。

3、Android 4.4 ART 和 AOT 登场

在 Android 4.4 带来了全新的虚拟机运行环境 ART 和全新的编译策略 AOT,此时 ART 和 Dalvik 是共存的。

4、Android 5.0 ART 全面取代 Dalvik

此时Dalvik VM退出历史舞台,AOT 也成为了唯一的编译方式。

5、Android 7.0 JIT 回归

形成了 AOT / JIT 混合编译模式。该混合模式综合了 AOT 和 JIT 的各种优点,使得应用在安全速度加快的同时,运行速度、存储空间和耗电量等指标都得到了优化。

二、DVM与JVM区别

1、基于的架构不同

JVM基于栈,要去栈中读写数据,在复制数据时而使用大量的出入栈指令。所需的指令会更多。对于性能有限的移动设备样会导致速度变慢。

DVM是基于寄存器的,指令更紧凑、更简洁。由于显式指定了操作数,所以基于寄存器的指令会比基于栈的指令要大,但是由于指令数量的减少,总的代码数不会增加多少。

2、执行的字节码不同

java源文件经过javac编译器编译成class文件,jvm执行的为class文件

java源文件经过javac编译器编译成class文件,而class文件经过dx工具被编译成dex文件,dvm执行的为dex文件

问题:安卓dvm为啥这样设计,向jvm那样执行class文件不好吗?
每个class文件里面包含了该类的常量池、类信息、属性等。当JVM加载多个class文件的时候,会加载里面的所有的class文件,JVM的这种加载方式很慢,对于内存有限的移动设备并不合适。而在apk文件中只包含了一个dex文件,这个dex文件将所有的class里面所包含的信息全部整合在一起了,这样再加载就加快了速度。

3、DVM允许在有限的内存中同时运行多个进程

Android中的每一个应用都运行在一个DVM 实例中,每一个DVM 实例都运行在一个独立的进程空间中,独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

4、DVM由Zygote创建和初始化

Zygote是一个DVM进程,同时也用来创建和初始化DVM实例。

每当系统需要创建一个应用程序时,Zygote就会fock自身,快速地创建和初始化一个DVM实例,用于应用程序的运行。

对于一些只读的系统库,所有的DVM实例都会和Zygote共享一块内存区域,节省了内存开销。

5、DVM有共享机制

安卓基于linux系统,应用进程之间可以通过共享内存进行共享内存数据,而不同的java程序运行在不同的jvm进程中,jvm运行在操作系统上,jvm未提供共享机制。

6、DVM早期没有使用JIT编译器

早期的DVM每次执行代码,都需要通过解释器将dex代码编译成机器码,然后交给系统处理,效率不是很高。

Android 2.2版本开始DVM使用了JIT 编译器,它会对多次运行的代码(热点代码)进行编译,生成相当精简的本地机器码(Native Code),这样在下次执行到相同逻辑的时候,直接使用编译之后的本地机器码,而不是每次都需要编译。

需要注意的是,应用程序每一次重新运行的时候,都要重做编译工作,因此每次重新打开应用程序,都需要JIT编译

三、DVM的架构

在这里插入图片描述
Java编译器编译的.class 文件经过DX工具转换为.dex文件,dex文件由类加载器处理,接着解释器根据指令集对Dalvik字节码进行解释、执行,最后交于Linux处理。

四、 DVM的运行时堆

在这里插入图片描述
DVM的运行时堆gc算法:标记—清除(Mark-Sweep)算法

DVM的运行时堆组成:

  • Zygote Space(Zygote Heap)
  • Allocation Space (Active Heap)
  • Card Table:用于DVM Concurrent GC,当第一次进行垃圾标记后,记录垃圾信息
  • Heap Bitmap:有两个Heap Bitmap,一个用来记录上次GC存活的对象,另一个用来记录这次GC存活的对象。
  • Heap Bitmap:有两个Heap Bitmap,一个用来记录上次GC存活的对象,另一个用来记录这次GC存活的对象。

在Zygote进程fork第一个子进程之前,会把Zygote Space分为两个部分,原来的已经被使用的那部分堆仍旧叫Zygote Space,而未使用的那部分堆就叫Allocation Space,以后的对象都会在Allocation Space上进行分配和释放。

五、ART与DVM区别

1、运行效率

运行效率的区别其实是AOT与JIT编译器的区别。

DVM:应用每次运行时,字节码都需要通过JIT编译器编译为机器码,这会使得应用程序的运行效率降低

ART:
系统在安装应用程序时会进行一次AOT(ahead of time compilation,预编译),将字节码预先编译成机器码并存储在本地,这样应用程序每次运行时就不需要执行编译了,运行效率会大大提升,设备的耗电量也会降低

2、CUP设计

DVM:为32位CPU设计

ART:支持64位并兼容32位CPU

3、垃圾回收

ART相对DVM:ART对垃圾回收进行了改进,更频繁地执行并行垃圾收集,将GC暂停由2次减少为1次等。

4、运行时控件堆的划分

ART采用了多种垃圾收集方案,默认是采用标记清除法(CMS)

ART的运行时堆的空间默认是由4个Space和多个辅助数据结构组成。

(1)4 Space

  • Zygote Space:与DVM一致
  • Allocation Space:与DVM一致
  • Image Space:存放一些预加载类,进程间共享
  • Large Object Space:分配一些大对象(默认大小为12KB)

(2)多个数据结构

  • 两个Mod Union Table
  • 一个CardTable
  • 两个Heap Bitmap
  • 两个Object Map
  • 三个Object Stack

AOT与JIT的区别

1、AOT优缺点

优点:

  • 应用启动快,运行更加流畅。

  • 耗电问题得到优化

缺点:

  • 安装应用时需要预编译相对耗时
  • 优化后的文件占额外的空间
2、JIT优缺点

优点:

  • 热点代码得到编译

缺点:

  • 每次应用启动都需要编译

  • 运行时更加耗电

The end

参考 :
安卓进阶解密:微信读书版

https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Dalvik%20%E5%92%8C%20ART.md

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值