JVM和Dalvik VM

来源传智播客Android培训学院

部分来源于知乎 作者:天光    链接:https://www.zhihu.com/question/20207106/answer/14654536

Dalvik虚拟机是Google公司自主设计的运行于Android平台的Java虚拟机。JVM是归Oracle公司所有的,运行在基于PC机上的Window 和Linux操作系上的java虚拟机。Google工程师之所以设计Dalvik虚拟机主要有以下两点原因:若要使用JVM需要获得授权许可,这意味着需要缴纳大量的费用;JVM主要是针对于CPU快,内存大的传统PC机,不适合移动设备。

JAVA 虚拟机(JVM) 是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的,它有自己完善的硬件架构(如堆栈、处理器、寄存器),还具有响应的指令系统。使用“Java 虚拟机”程序就是为了支持与操作系统无关,在任何系统中投可以运行的程序。

Dalvik 虚拟机是android程序中的虚拟机,是android 中java程序运行的基础,器指令集基于寄存器架构,执行其特有的 文件格式-dex字节码来完成对对象的生命周期管理、堆栈管理、线程管理、安全异常管理

垃圾回收等重要功能,它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于Linux内核的一部分功能-线程机制、内存管理机制。能高效使用内存,并在低速CPU上表现出高性能。

1. 对比两种虚拟机


Dalvik和JVM两种不同的虚拟机比较如下图1-1所示:
图1-1两种虚拟机的比较

通过对比上图我们可以得出如下几点区别:
(1)Java虚拟机运行java字节码,Dalvik虚拟机运行其专有的文件格式.dex。
(2)为了进一步提高运行速度,Dalivk虚拟机可以运行八进制的文件.odex。
(3)Dalvik基于寄存器,而JVM基于栈。基于寄存器的虚拟机对于编译之后变大的程序来说,在它们执行时候,花费的时间更短。

dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机实例,并且每一个dalvik都作为一个单独的Linux进程执行。

2. 对比两种虚拟机编译的文件


下图是两种不同虚拟机编译文件格式的对比,左图是JAVA虚拟机常用的.Class文件,右图是Dalvik虚拟机运行的.dex文件。下面展示的是.class文件转换为.dex文件的过程图,如图1-2所示。
图1-2.class文件转换成.dex


JVM的可执行文件是.class格式,每一个.java文件经过编译之后都要生成ClassFile文件。ClassFile文件是由一个8位的字节流组成的,每一个ClassFile都有固定的格式。从左图可以看出一个.class文件包含的字段:
l Header:头文件用来记录当前自解码的版本以及文件的格式。
l Contant Pool:常量池,存储常量。例如:Public static final String str =”itcast”便会存放在常量池中。
l Class:自解码真正的内容,包含filed,Method,Attributes。
传统的JVM在执行代码时会有多个相同结构的ClassFile文件,Google工程师在编写Dalvik虚拟机时将这些格式相同的ClassFile文件合并成.dex文件,在合并这些文件的同时对.class文件中都出现的常量进行提取并放在常量池(String Constant Pool)中,类常量,字段常量,方法常量也以此类推。这种做法使移动平台能够更快的解析各个文件,提高效率。.odex文件格式是对.dex格式文件的进一步优化。


3.本质区别

  •  其核心差异是Dalvik VM架构是register-based,JVM是stack-based的。也就是架构上的差异。reg based VM的好处是可以做到更好的提前优化。 另外reg based的VM执行起来更快,但是代价是更大的代码长度。
  • Dalivik允许多个实例的运行,也就是说每一个Android 的App是独立跑在一个VM中.这样做的好处是一个App crash只会影响到自身的VM,不会影响到其他。 Dalvik的设计是每一个Dalvik的VM都是Linux下面的一个进程。那么这就需要高效的IPC。另外每一个VM是单独运行的好处还有可以动态active/deactive自己的VM而不会影响到其他VM。
  • 当然stack based的VM也有其优点,就是它不对host平台的reg数量做假设,有利于移植到不同的平台。而Dalvik则不关心这些,因为它本来就是为ARM这样的多reg平台设计的。另外Dalvik被移植到x86也说明,即使是x86这种寄存器很少的平台,基于寄存器的VM也是没有问题的。


下面着重说DVM的优势:

   1、在编译时提前优化代码而不是等到运行时。
   2、虚拟机很小,因此使用的空间也小,被设计了来满足可高效运行多种虚拟机实例。
   3、常量池已被修改为只使用32位的索引,以简化解释器。
 
现在实际的处理器,大多都是基于寄存器的架构,从侧面反映出基于寄存器比基于栈的架构更与实际的处理器接近。但对于VM来说,源架构的求值 栈或者寄存器都可能是用实际机器的内存来模拟的,所以性能特性与实际硬件又有不同。一般认为基于寄存器架构的Dalvik VM比基于栈架构JVM执行效率更高,原因是:虽然零地址指令更紧凑,但完成操作需要更多的load/store指令,也意味着更多的指令分派 (instruction dispatch)次数与内存访问次数;访问内存是执行速度的一个重要瓶颈,二地址或三地址指令虽然每条指令占的空间较多,但总体来说可以用更少的指令完 成操作,指令分派与内存访问次数都较少。

在一个解释器上执行 VM 指令,包含三个步骤,指令分派、访问操作数和执 行计算。 
  • 指令分派(Instructions dispatch)负责从内存中读取 VM 指令,然后跳转到相应的解释器代码 指令分派 中。上面提到过,完成同样的事情,基于栈的虚拟机需要更多的指令,意味着更多的指令分派和 内存访问次数,这是 JVM 的执行性能不如 Dalvik VM 的原因之一。
  • 访问操作数 访问操作数(Operands access)是指读取和写回源操作数和目的操作数。Dalvik VM 通过虚拟 操作数 寄存器来访问操作数, 由于具有相近的血缘, Dalvik 的虚拟寄存器在映射到物理寄存器方面具有 更充分的优势, 这也是 Dalvik VM 性能较佳的一个原因。 JVM 的操作数通过操作数栈来访问, 而 因为指令中没有使用任何通用寄存器,在虚拟机的实现中可以比较自由的分配实际机器的寄存 器,因而可移植性高。作为一个优化,操作数栈也可以由编译器映射到物理寄存器上,减少数据 移动的开销。
  • 指令执行(Instructions compute)这个似乎没什么可解释的,老老实实执行就行。
一个应用中会定义很多类, 编译完成后即会有很多相应 的CLASS文件,CLASS文件 间会有不少冗余的信息。
dex字节码和标准Java的字节码(Class)在结构上的一个区别是dex字节码将多个文件整合成一个,这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找速度。
原来每个类文件中的常量池现在由DEX文件中一个常量池来管理。

DEX文件可以进行进一步优化。优化主要是针对以下几个方面:

1、调整所有字段的字节序(LITTLE_ENDIAN)和对齐结构中的没一个域
2、验证DEX文件中的所有类
3、对一些特定的类进行优化,对方法里的操作码进行优化

优化 优化后的文件大小会有所增加,应该是原DEX文件的1-4倍。 odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化 。

每一个Android应用都运行在一个Dalvik虚拟机实例里,而每一个虚拟机实例都是一个独立的进程空间。每个进程之间可以通信(IPC,Binder机制实现)。虚拟机的线程机制,内存分配和管理,Mutex等等都是依赖底层操作系统而实现的。


不同的应用在不同的进程空间里运行,当一个虚拟机关闭或意外中止时不会对其它虚拟机造成影响,可以最大程度的保护应用的安全和独立运行。
Zygote是虚拟机实例的孵化器。AndroidRuntime.cpp中ZygoteInit.main()的执行会完成一个分裂,分裂出来的子进程继续初始化Java层的架构,这个分裂出来的进程就是system_server。每当系统要求执行一个Android应用程序,Zygote就会FORK出一个子进程来执行该应用程序。这样做的好处显而易见:Zygote进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等等操作,而在系统需要一个新的虚拟机实例时,Zygote通过复制自身,最快速的提供个系统。另外,对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域,大大节省了内存开销。








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值