Android DVM(Dalvik Virtual Machine)和Java JVM(Java Virtual Machine)以及ART(Android RunTime)概述
JVM,Java Virtual Machine,Java虚拟机,JVM是基于栈的虚拟机,JVM栈是内存中连续的存储空间。JVM优点是相对简单,实现了Java的跨平台。Android使用Java编程设计语言,DVM(Dalvik Virtual Machine )作为其虚拟机,Android App运行在系统进程里,每个进程对应着一个Dalvik虚拟机实例。
一个Android应用启动后运行在一个单独的Dalvik VM中,每一个Dalvik VM运行在一个单独的Linux进程中。Dalvik VM可在有限内存空间中同时运行多个Dalvik虚拟机实例。因此每一个Android应用作为一个独立的Linux 进程执行,作为安全隔离,该独立进程可以防止在Dalvik虚拟机崩溃时导致所有Android程序都被影响。
Dalvik虚拟机在Android 2.2之后使用JIT (Just-In-Time)技术,与传统JVM的JIT并不完全一致。每一个Android应用在系统底层都会对应一个独立的DVM实例,其代码在虚拟机的解释下执行。Android应用的线程对应一个Linux线程,Dalvik虚拟机因此可以使用Linux操作系统内核的线程调度和管理机制。
Android DVM执行的是.dex文件(Dalvik Executable,以ODEX结尾),dex是专为Dalvik VM设计的一种文件压缩格式。Dalvik虚拟机有自己的 ByteCode,并非使用Java ByteCode。Java JVM执行.class字节码文件。对比Java的.jar和Android的.dex产生过程:
Java:
.java -- .class -- .jar
Android:
.java -- .class -- .dex
可以简单认为dex是若干class等Android资源的“归整”。多个class文件合并成一个dex文件所带来的问题,是方法数量超过65535编译错误,解决方案是MultiDex。
DVM是基于寄存器的虚拟机,JVM是基于栈的虚拟机。基于寄存器的DVM编译和运行时存取速度比栈快,DVM适合移动设备。JVM基于栈结构,代码在编译和运行时虚拟机须频繁从栈读写数据,此过程需要额外多的指令与内存访问,显然DVM速度更快。
DVM在GC时单独申请一块内存空间,以位图Bitmap形式来保存堆上对象的标记,GC结束后就释放该空间。 DVM GC策略默认是标记擦除垃圾回收算法,即Mark和Sweep两个阶段。Mark阶段使用两个Bitmap来描述堆的对象,一个为Live Bitmap,另一个Mark Bitmap。Live Bitmap标记上一次GC时被引用的对象,也就是没有被回收的对象,Mark Bitmap用来标记当前GC有被引用的对象。
Android 4.4发布ART(Android RunTime)。Android L后,ART取代DVM。ART虚拟机直接执行本地机器码。DVM运行的dex字节码需要通过解释器执行。作为兼容性考虑,ART环境下,Android应用程序仍然可以是一个包含dex的apk文件。在ART中,apk运行前,先对apk中的dex字节码进行解释翻译,取得到对应的本地Android机器指令,然后就可以在ART中直接执行。ART在安装apk(Android App)时就把dex中字节码随即编译成本地机器码,之后每次启动App,执行的即是本地机器码(类似于Windows下的exe文件)。ART省去了运行时解释执行,效率更高,速度更快。