Dalvik虚拟机浅识

       Java虚拟机(JVM) 是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。它有自己完善的硬件架构(如处理器、堆栈、寄存器等),还具有相应的指令系统。 其指令集基于栈架构,执行其特有的*.class文件格式 . 使用“Java虚拟机”程序就是为了支持与操作系统无关、在任何系统中都可以运行的程序。
          Android Dalvik虚拟机 是Android程序的虚拟机,是Android中Java程序的运行基础。 其指令集基于寄存器架构,执行其特有的*.dex文件格式。 通过dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于 Linux 内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。 每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行
Dalvik VM Apache Harmony 项目关系源远流长,因此,与 JVM 关系自然就密切了。
然而: Dalvik VM ≠Java VM
dalvik基于寄存器,而JVM基于栈
Dalvik虚拟机 执行的是特有的 *.dex文件格式 ,而JVM运行的是*.class文件格式。
Dalvik虚拟机 有以下几个优势:
        1、在编译时提前优化代码而不是等到运行时
        2、 虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。
3、常量池已被修改为只使用32位的索引,以简化解释器
JVM 的字节码主要是零地址形式的,概念上说 JVM是基于栈的架构 Android 平台上应用程序的主要开发语言是 Java
它通过其中的 Dalvik VM 来运行 Java 程序。为了能正确实现语义, Dalvik VM 的许多设计都考虑到与 JVM 的兼容性;但它却采用了 基于寄存器 的架构,其字节码主要是 二地址/三地址的混合形式
         基于栈与基于寄存器的架构,谁更快?现在实际的处理器,大多都是基于寄存器的架构,从侧面反映出 基于寄存器比基于栈的架构更与实际的处理器接近 。但对于 VM 来说,源架构的求值栈或者寄存器都可能是用实际机器的内存来模拟的,所以性能特性与实际硬件又有不同。 一般认为基于寄存器架构的Dalvik VM比基于栈架构JVM执行效率更高 ,原因是: 虽然零地址指令更紧凑,但完成操作需要更多的load/store指令,也意味着更多的指令分派(instruction dispatch)次数与内存访问次数;访问内存是执行速度的一个重要瓶颈,二地址或三地址指令虽然每条指令占的空间较多,但总体来说可以用更少的指令完成操作,指令分派与内存访问次数都较少 。 
另外,关于JVM的指令集的详细内容请阅读《 JVM指令详解
我们从下面的 图1图2 可以看到与同一段Java代码对应的Java bytecode 与Dalvid bytecode的比较。
图1
Dalvik虚拟机浅识_第1张图片
图2  
Dalvik虚拟机浅识_第2张图片
 注意 :JVM中,并不是每条指令都占一个单元的,比如 if_icmple,ifeq 等指令
      一个应用中会定义很多类,编译完成后即会有很多相应的 class 文件, class 文件间会有不少冗余的信息。
dex字节码和标准Java的字节码(Class)在结构上的一个区别是 dex字节码将多个文件整合成一个 ,这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找速度。 原来每个类文件中的常量池现在由 DEX文件中一个常量池来管理
   对于 Android JAVA 应用程序,是先把用 JDK Java源码 编译成 *.class 文件,然后再用 Android 提供的 DX工具 转化为 *.dex 文件的。如图3
   另外, dex文件 可以进行进一步优化生成 odex文件 优化后的dex文件大小会有所增加,应该是原dex文件的1-4倍。
优化主要是针对以下几个方面:
1、调整所有字段的字节序(LITTLE_ENDIAN)和对齐结构中的没一个域 
2、验证dex文件中的所有类 
3、对一些特定的类进行优化,对方法里的操作码进行优化
图3
Dalvik虚拟机浅识_第3张图片
每一个Android应用都运行在一个Dalvik虚拟机实例里 ,而每一个虚拟机实例都是一个独立的进程空间。每个进程之间可以通信(IPC,Binder机制实现)。虚拟机的线程机制,内存分配和管理,Mutex等等都是依赖底层操作系统而实现的。
    不同的应用在不同的进程空间里运行 ,当一个虚拟机关闭或意外中止时不会对其它 虚拟机造成影响,可以最大程度的保护应用的安全和独立运行。
  Zygote 是虚拟机实例的孵化器。 AndroidRuntime.cpp 中调用 com.android.internal.os 中的 ZygoteInit 类的 main()方法, 执行会完成一个分裂,分裂出来的子进程继续初始化 Java 层的架构,这个分裂出来的进程就是 system_server 。每当系统要求执行一个 Android 应用程序, Zygote 就会 FORK 一个子进程 来执行该应用程序。这样做的好处显而易见: Zygote 进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等等操作,而在系统需要一个新的虚拟机实例时, Zygote 通过复制自身,最快速的提供个系统。关于此可以参见 图4图5 . 另外,对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域,大大节省了内存开销。
图4
Dalvik虚拟机浅识_第4张图片
 
图5
Dalvik虚拟机浅识_第5张图片

你可能感兴趣的:(Dalvik虚拟机浅识)