Android Dalvik虚拟机简介

本文详细阐述了Java虚拟机(JVM)的概念、架构及指令集,以及Android平台下Dalvik虚拟机的独特之处,包括其基于寄存器的架构、执行*.dex文件格式的特性以及与JVM的兼容性。文章还对比了两者在架构、性能及应用方面的差异,特别是Dalvik VM相较于JVM在执行效率上的优势。同时,文章提供了直观的图表展示Java与Dalvik字节码的区别,以及优化dex文件的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文章编辑自:<wbr style="line-height:25px"><a rel="nofollow" href="http://carvencao.blog.sohu.com/154325146.html" style="color:rgb(207,121,28); line-height:25px; text-decoration:none">http://carvencao.blog.sohu.com/154325146.html</a> <div style="line-height:25px"> <span style="color:#003366; line-height:25px"></span><span style="color:#0000ff; line-height:25px">Java虚拟机(JVM)</span><span style="color:#003366; line-height:25px">是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。它有自己完善的硬件架构(如处理器、堆栈、寄存器等),还具有相应的指令系统。</span><span style="color:#0000ff; line-height:25px">其指令集基于栈架构,执行其特有的*.class文件格式</span><span style="line-height:25px; color:rgb(0,51,102)">.</span><span style="line-height:25px; color:rgb(0,51,102)">使用“Java虚拟机”程序就是为了支持与操作系统无关、在任何系统中都可以运行的程序。</span> </div> <div style="line-height:25px"> <span style="color:#0000ff; line-height:25px">AndroidDalvik虚拟机</span><span style="color:#003366; line-height:25px">是Android程序的虚拟机,是Android中Java程序的运行基础。</span><span style="color:#0000ff; line-height:25px">其指令集基于寄存器架构,执行其特有的*.dex文件格式。</span><span style="color:#000080; line-height:25px">它</span><span style="color:#003366; line-height:25px">通过dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于</span><span style="color:#0000ff; line-height:25px">Linux</span><span style="color:#003366; line-height:25px">内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。</span><span style="color:#ff6600; line-height:25px">每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行</span><span style="color:#003366; line-height:25px">。</span> </div> <div style="line-height:25px"> <div style="line-height:25px"> <span style="color:#0000ff; line-height:25px">Dalvik VM</span><span style="color:#000080; line-height:25px">与</span><span style="color:#0000ff; line-height:25px">Apache Harmony</span><span style="color:#000080; line-height:25px">项目关系源远流长,因此,与</span><span style="color:#0000ff; line-height:25px">JVM</span><span style="color:#000080; line-height:25px">关系自然就密切了。</span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px">然而:</span><span style="color:#ff6600; line-height:25px">Dalvik VM ≠Java VM</span> </div> <div style="line-height:25px"><span style="color:#0000ff; line-height:25px">dalvik基于寄存器,而JVM基于栈</span></div> <div style="line-height:25px"> <span style="color:#0000ff; line-height:25px">Dalvik虚拟机</span><span style="color:#000080; line-height:25px">执行的是特有的</span><span style="color:#0000ff; line-height:25px">*.dex文件格式</span><span style="color:#000080; line-height:25px">,而JVM运行的是*.class文件格式。</span> </div> <div style="line-height:25px"> <span style="color:#0000ff; line-height:25px">Dalvik虚拟机</span><span style="color:#000080; line-height:25px">有以下几个优势:</span> </div> <div style="line-height:25px"><span style="color:#0000ff; line-height:25px"> 1、在编译时提前优化代码而不是等到运行时</span></div> <div style="line-height:25px"><span style="color:#0000ff; line-height:25px"> 2、 虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。</span></div> <div style="line-height:25px"><span style="color:#0000ff; line-height:25px"><span style="line-height:25px; white-space:pre"></span>3、常量池已被修改为只使用32位的索引,以简化解释器</span></div> </div> <div style="line-height:25px"> <span style="color:#0000ff; line-height:25px">JVM</span><span style="color:#000080; line-height:25px">的字节码主要是零地址形式的,概念上说</span><span style="color:#0000ff; line-height:25px">JVM是基于栈的架构</span><span style="color:#000080; line-height:25px">。</span><span style="color:#0000ff; line-height:25px">Android</span><span style="color:#000080; line-height:25px">平台上应用程序的主要开发语言是</span><span style="color:#0000ff; line-height:25px">Java</span><span style="color:#000080; line-height:25px">,</span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px">它通过其中的</span><span style="color:#0000ff; line-height:25px">Dalvik VM</span><span style="color:#000080; line-height:25px">来运行</span><span style="color:#0000ff; line-height:25px">Java</span><span style="color:#000080; line-height:25px">程序。为了能正确实现语义,</span><span style="color:#0000ff; line-height:25px">Dalvik VM</span><span style="color:#000080; line-height:25px">的许多设计都考虑到与</span><span style="color:#0000ff; line-height:25px">JVM</span><span style="color:#000080; line-height:25px">的兼容性;但它却采用了</span><span style="color:#0000ff; line-height:25px">基于寄存器</span><span style="color:#000080; line-height:25px">的架构,其字节码主要是</span><span style="color:#0000ff; line-height:25px">二地址/三地址的混合形式</span><span style="color:#000080; line-height:25px">。</span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px"> 基于栈与基于寄存器的架构,谁更快?现在实际的处理器,大多都是基于寄存器的架构,从侧面反映出</span><span style="color:#0000ff; line-height:25px">基于寄存器比基于栈的架构更与实际的处理器接近</span><span style="color:#000080; line-height:25px">。但对于</span><span style="color:#0000ff; line-height:25px">VM</span><span style="color:#000080; line-height:25px">来说,源架构的求值栈或者寄存器都可能是用实际机器的内存来模拟的,所以性能特性与实际硬件又有不同。</span><span style="color:#ff6600; line-height:25px">一般认为基于寄存器架构的Dalvik VM比基于栈架构JVM执行效率更高</span><span style="color:#000080; line-height:25px">,原因是:</span><span style="color:#0000ff; line-height:25px">虽然零地址指令更紧凑,但完成操作需要更多的load/store指令,也意味着更多的指令分派(instruction dispatch)次数与内存访问次数;访问内存是执行速度的一个重要瓶颈,二地址或三地址指令虽然每条指令占的空间较多,但总体来说可以用更少的指令完成操作,指令分派与内存访问次数都较少</span><span style="color:#000080; line-height:25px">。</span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px">另外,关于JVM的指令集的详细内容请阅读《</span><strong><a title="阅读全文" target="_blank" href="http://hubingforever.blog.163.com/blog/static/17104057920117822653653/" style="color:rgb(207,121,28); line-height:25px; text-decoration:none">JVM指令详解</a></strong><span style="line-height:25px; color:rgb(0,0,128)">》</span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px">我们从下面的</span><span style="line-height:25px">图1</span>和<span style="line-height:25px">图2</span><span style="color:#000080; line-height:25px">可以看到与同一段Java代码对应的Java bytecode 与Dalvid bytecode的比较。</span> </div> <div style="line-height:25px"><span style="color:#000080; line-height:25px"><span style="line-height:25px">图1</span></span></div> <div style="line-height:25px"> <div style="line-height:25px; color:rgb(0,0,128)"><img alt="Android Dalvik虚拟机简介 - hubingforever - 民主与科学" src="http://img.ph.126.net/LtgcA1ha2JIrEzCpCUUwqA==/2886525886184642588.jpg" style="line-height:25px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; max-width:100%; margin-top:0px; margin-right:10px; margin-bottom:0px; margin-left:0px"></div> <span style="line-height:25px">图2</span><span style="color:#000080; line-height:25px"></span> </div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px"></span> <div style="line-height:25px"><img alt="Android Dalvik虚拟机简介 - hubingforever - 民主与科学" src="http://img.ph.126.net/Hgse4DjfemmSZE75DPevJg==/2769713770849720213.jpg" style="line-height:25px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; max-width:100%; margin-top:0px; margin-right:10px; margin-bottom:0px; margin-left:0px"></div> </div> <div style="line-height:25px"> <span style="line-height:25px">注意</span><span style="color:#000080; line-height:25px">:JVM中,并不是每条指令都占一个单元的,比如</span><span style="color:#ff6600; line-height:25px"><span style="line-height:25px">if_icmple</span>,<span style="line-height:25px">ifeq</span></span><span style="color:#000080; line-height:25px">等指令</span> </div> <div style="line-height:25px"> <div style="line-height:25px"> <span style="color:#003366; line-height:25px"> 一个应用中会定义很多类,编译完成后即会有很多相应的</span><span style="color:#0000ff; line-height:25px">class</span><span style="color:#003366; line-height:25px">文件,</span><span style="color:#0000ff; line-height:25px">class</span><span style="color:#003366; line-height:25px">文件间会有不少冗余的信息。</span> </div> <div style="line-height:25px"> <span style="color:#003366; line-height:25px">dex字节码和标准Java的字节码(Class)在结构上的一个区别是</span><span style="color:#ff6600; line-height:25px">dex字节码将多个文件整合成一个</span><span style="color:#003366; line-height:25px">,这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找速度。</span><span style="color:#003366; line-height:25px">原来每个类文件中的常量池现在由</span><span style="color:#0000ff; line-height:25px">DEX文件中一个常量池来管理</span><span style="color:#003366; line-height:25px">。</span> </div> <div style="line-height:25px"> <span style="color:#003366; line-height:25px"> 对于</span><span style="color:#0000ff; line-height:25px">Android</span><span style="color:#003366; line-height:25px">的</span><span style="color:#0000ff; line-height:25px">JAVA</span><span style="color:#003366; line-height:25px">应用程序,是先把用</span><span style="color:#0000ff; line-height:25px">JDK</span><span style="color:#003366; line-height:25px">把</span><span style="color:#0000ff; line-height:25px">Java源码</span><span style="color:#003366; line-height:25px">编译成</span><span style="color:#0000ff; line-height:25px">*.class</span><span style="color:#003366; line-height:25px">文件,然后再用</span><span style="color:#0000ff; line-height:25px">Android</span><span style="color:#003366; line-height:25px">提供的</span><span style="color:#0000ff; line-height:25px">DX工具</span><span style="color:#003366; line-height:25px">转化为</span><span style="color:#0000ff; line-height:25px">*.dex</span><span style="color:#003366; line-height:25px">文件的。如<span style="line-height:25px">图3</span></span> </div> <div style="line-height:25px"> <span style="color:#003366; line-height:25px"> 另外,</span><span style="color:#ff6600; line-height:25px">dex文件</span><span style="color:#003366; line-height:25px">可以进行进一步优化生成</span><span style="color:#ff6600; line-height:25px">odex文件</span><span style="color:#003366; line-height:25px">。</span><span style="line-height:25px; color:rgb(0,51,102)">优化后的dex文件大小会有所增加,应该是原dex文件的1-4倍。</span> </div> <div style="line-height:25px"><span style="line-height:25px; color:rgb(0,51,102)">优化主要是针对以下几个方面:</span></div> <div style="line-height:25px"><span style="color:#000080; line-height:25px"><span style="line-height:25px; white-space:pre"></span>1、调整所有字段的字节序(LITTLE_ENDIAN)和对齐结构中的没一个域</span></div> <div style="line-height:25px"><span style="color:#000080; line-height:25px"><span style="line-height:25px; white-space:pre"></span>2、验证dex文件中的所有类</span></div> <div style="line-height:25px"><span style="color:#000080; line-height:25px"><span style="line-height:25px; white-space:pre"></span>3、对一些特定的类进行优化,对方法里的操作码进行优化</span></div> <div style="line-height:25px"><span style="line-height:25px">图3</span></div> </div> <div style="line-height:25px"> <div style="line-height:25px; color:rgb(0,51,102); font-weight:bold"><img alt="Android Dalvik虚拟机简介 - hubingforever - 民主与科学" src="http://img.ph.126.net/k-X8dW4gZnM58HKylzPqew==/2546222639341458313.jpg" style="line-height:25px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; max-width:100%; margin-top:0px; margin-right:10px; margin-bottom:0px; margin-left:0px"></div> <div style="line-height:25px"> <div style="line-height:25px"> <span style="color:#ff6600; line-height:25px">每一个Android应用都运行在一个Dalvik虚拟机实例里</span><span style="color:#003366; line-height:25px">,而每一个虚拟机实例都是一个独立的进程空间。每个进程之间可以通信(IPC,Binder机制实现)。虚拟机的线程机制,内存分配和管理,Mutex等等都是依赖底层操作系统而实现的。</span> </div> <div style="line-height:25px"> <span style="line-height:25px; color:rgb(0,51,102)"> </span><span style="color:#ff6600; line-height:25px">不同的应用在不同的进程空间里运行</span><span style="color:#003366; line-height:25px">,当一个虚拟机关闭或意外中止时不会对其它 虚拟机造成影响,可以最大程度的保护应用的安全和独立运行。</span> </div> <div style="line-height:25px"> <span style="line-height:25px; color:rgb(0,51,102)"></span><span style="color:#0000ff; line-height:25px">Zygote</span><span style="color:#003366; line-height:25px">是虚拟机实例的孵化器。</span><span style="color:#0000ff; line-height:25px">AndroidRuntime.cpp</span><span style="color:#003366; line-height:25px">中调用</span><span style="color:#0000ff; line-height:25px">com.android.internal.os</span><span style="line-height:25px; color:rgb(0,51,102)">中的</span><span style="color:#0000ff; line-height:25px">ZygoteInit</span><span style="line-height:25px; color:rgb(0,51,102)">类的</span><span style="color:#0000ff; line-height:25px">main()方法,</span><span style="color:#003366; line-height:25px">执行会完成一个分裂,分裂出来的子进程继续初始化</span><span style="color:#0000ff; line-height:25px">Java</span><span style="color:#003366; line-height:25px">层的架构,这个分裂出来的进程就是</span><span style="color:#0000ff; line-height:25px">system_server</span><span style="color:#003366; line-height:25px">。每当系统要求执行一个</span><span style="color:#0000ff; line-height:25px">Android</span><span style="color:#003366; line-height:25px">应用程序,</span><span style="color:#0000ff; line-height:25px">Zygote</span><span style="color:#003366; line-height:25px">就会</span><span style="color:#0000ff; line-height:25px">FORK</span><span style="color:#003366; line-height:25px">出</span><span style="color:#0000ff; line-height:25px">一个子进程</span><span style="color:#003366; line-height:25px">来执行该应用程序。这样做的好处显而易见:</span><span style="color:#0000ff; line-height:25px">Zygote</span><span style="color:#000080; line-height:25px">进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等等操作,而在系统需要一个新的虚拟机实例时,</span><span style="color:#0000ff; line-height:25px">Zygote</span><span style="color:#000080; line-height:25px">通过复制自身,最快速的提供个系统。关于此可以参见</span><span style="line-height:25px">图4</span>和<span style="line-height:25px">图5</span><span style="color:#000080; line-height:25px">.</span><span style="color:#003366; line-height:25px">另外,对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域,大大节省了内存开销。</span> </div> </div> </div> <div style="line-height:25px"><span style="line-height:25px">图4</span></div> <div style="line-height:25px"> <span style="color:#003366; line-height:25px"></span> <div style="line-height:25px"><img alt="Android Dalvik虚拟机简介 - hubingforever - 民主与科学" src="http://img.ph.126.net/TOL4-NeyDqxighgUSz9mgg==/2732840548900624314.jpg" style="line-height:25px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; max-width:100%; margin-top:0px; margin-right:10px; margin-bottom:0px; margin-left:0px"></div> </div> <div style="line-height:25px"><span style="line-height:25px">图5</span></div> <div style="line-height:25px"> <span style="color:#000080; line-height:25px"></span> <div style="line-height:25px"><img alt="Android Dalvik虚拟机简介 - hubingforever - 民主与科学" src="http://img.ph.126.net/qq085q7oxSCcPJMBm7pTdg==/1090152584817234546.jpg" style="line-height:25px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; max-width:100%; margin-top:0px; margin-right:10px; margin-bottom:0px; margin-left:0px"></div> </div> <div style="line-height:25px">结束!</div> </wbr>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值