摘自:http://blog.csdn.net/andyxm/article/details/6126907安全
首先,让咱们来思考下面几个问题:架构
什么是Dalvik虚拟机?性能
Dalvik VM与JVM有什么区别?优化
Dalvik VM有什么新的特色?this
Dalvik VM的架构是怎么样的?spa
首先,我得认可第一个问题问得很傻:什么是Dalvik虚拟机?没有人给出过一个明确的定义,可是,咱们彷佛能够从人们对Java虚拟机的描述中获得些信息。操作系统
Java虚拟机(JVM)是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。它有本身完善的硬件架构(如处理器、堆栈、寄存器等),还具备相应的指令系统。使用“Java虚拟机”程序就是为了支持与操做系统无关、在任何系统中均可以运行的程序。.net
所以,咱们不妨对Dalvik虚拟机做出这样的描述: 线程
Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其指令集基于寄存器架构,执行其特有的文件格式——dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大致由C语言实现。依赖于Linux内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。每个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。设计
与Dalvik虚拟机关系最密切的非JVM莫属,在Android源码readme文档中有这样一段话:Much of the code under this directory originally came from the Apache Harmony project, and as such contains the standard Apache header comment. Some of the code was written originally for the Android project…
Dalvik VM与Apache Harmony 项目关系源远流长,所以,与JVM关系天然就密切了。
然而:Dalvik VM ≠Java VM
dalvik基于寄存器,而JVM基于stack
Dalvik执行的是特有的DEX文件格式,而JVM运行的是*.class文件格式。
优点:
一、在编译时提早优化代码而不是等到运行时
二、 虚拟机很小,使用的空间也小;被设计来知足可高效运行多种虚拟机实例。
三、常量池已被修改成只使用32位的索引,以 简化解释器
JVM的字节码主要是零地址形式的,概念上说JVM是基于栈的架构。Google Android平台上的应用程序的主要开发语言是Java,经过其中的Dalvik VM来运行Java程序。为了能正确实现语义,Dalvik VM的许多设计都考虑到与JVM的兼容性;但它却采用了基于寄存器的架构,其字节码主要是二地址/三地址的混合形式。
基于栈与基于寄存器的架构,谁更快?如今实际的处理器,大多都是基于寄存器的架构,从侧面反映出基于寄存器比基于栈的架构更与实际的处理器接近。但对于VM来讲,源架构的求值栈或者寄存器均可能是用实际机器的内存来模拟的,因此性能特性与实际硬件又有不一样。通常认为基于寄存器架构的Dalvik VM比基于栈架构JVM执行效率更高,缘由是:虽然零地址指令更紧凑,但完成操做须要更多的load/store指令,也意味着更多的指令分派(instruction dispatch)次数与内存访问次数;访问内存是执行速度的一个重要瓶颈,二地址或三地址指令虽然每条指令占的空间较多,但整体来讲能够用更少的指令完成操做,指令分派与内存访问次数都较少。
咱们从下面的截图能够明了的看到与同一段Java代码对应的Java bytecode 与Dalvid bytecode的比较。
专有的DEX文件格式
一个应用中会定义不少类,
编译完成后即会有不少相应
的CLASS文件,CLASS文件
间会有很多冗余的信息。
dex字节码和标准Java的字节码(Class)在结构上的一个区别是dex字节码将多个文件整合成一个,这样,除了减小总体的文件尺寸,I/O操做,也提升了类的查找速度。
原来每一个类文件中的常量池如今由DEX文件中一个常量池来管理。
DEX文件能够进行进一步优化。优化主要是针对如下几个方面:
一、调整全部字段的字节序(LITTLE_ENDIAN)和对齐结构中的没一个域
二、验证DEX文件中的全部类
三、对一些特定的类进行优化,对方法里的操做码进行优化
优化 优化后的文件大小会有所增长,应该是原DEX文件的1-4倍。
odex是为了在运行过程当中进一步提升性能,对dex文件的进一步优化
一个应用,一个虚拟机实例,一个进程!!!
每个Android应用都运行在一个Dalvik虚拟机实例里,而每个虚拟机实例都是一个独立的进程空间。每一个进程之间能够通讯(IPC,Binder机制实现)。虚拟机的线程机制,内存分配和管理,Mutex等等都是依赖底层操做系统而实现的。
不一样的应用在不一样的进程空间里运行,当一个虚拟机关闭或意外停止时不会对其它 虚拟机形成影响,能够最大程度的保护应用的安全和独立运行。
Zygote是虚拟机实例的孵化器。AndroidRuntime.cpp中ZygoteInit.main()的执行会完成一个分裂,分裂出来的子进程继续初始化Java层的架构,这个分裂出来的进程就是system_server。每当系统要求执行一个Android应用程序,Zygote就会FORK出一个子进程来执行该应用程序。这样作的好处显而易见:Zygote进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等等操做,而在系统须要一个新的虚拟机实例时,Zygote经过复制自身,最快速的提供个系统。另外,对于一些只读的系统库,全部虚拟机实例都和Zygote共享一块内存区域,大大节省了内存开销。