Dalvik 虚拟机和 Sun JVM 在架构和执行方面有什么本质区别?
两者共同点:
- 都是解释执行 byte code
- 都是每个 OS 进程运行一个 VM,并执行一个单独的程序
- 在较新版本中(Froyo / Sun JDK 1.5)都实现了相当程度的 JIT compile 用于提速
根据 http://en.wikipedia.org/wiki/Dalvik_(software) ,两者不同点:
- Dalvik 的指令集与 Sun JVM 指令集不同。可由 Sun JVM 的 byte code 由 dx 工具处理生成 .dex 格式的中间码
- Dalvik 虚拟机架构是 register-based,与 Sun JDK 的 stack-based 不同
反对,不会显示你的姓名
其实其核心的差异,就是Dalvik 虚拟机架构是 register-based,与 Sun JDK 的 stack-based 不同,也就是架构上的差异。我先摘录几段网上可以找到的资料,重新整理和排版了一下,由于这些资料在网上经过多次转载,转发和加工,原作者不详,所以无法标注其原作者们,如有原作者认领或者质疑,请及时通知我。
其中部分资料为@RednaxelaFX 所著,特此感谢!
特别提供原文链接:
http://rednaxelafx.iteye.com/blog/492667
(1) Dalvik VM和JVM 的第一个区别是 Dalvik VM是基于寄存器的架构(reg based),而JVM是栈机(stack based)。reg based VM的好处是可以做到更好的提前优化(ahead-of-time optimization)。 另外reg based的VM执行起来更快,但是代价是更大的代码长度。
(2) 另外一个区别是Dalvik可以允许多个instance 运行,也就是说每一个Android 的App是独立跑在一个VM中.这样做的好处是一个App crash只会影响到自身的VM,不会影响到其他。 Dalvik的设计是每一个Dalvik的VM都是Linux下面的一个进程。那么这就需要高效的IPC。另外每一个VM是单独运行的好处还有可以动态active/deactive自己的VM而不会影响到其他VM
(3) 接下来就是关于版权之类争论。(可以参看下面文章)
既然reg based VM有那么多好处,为什么之前设计JAVA的人没有采用reg based而是采用stack based的呢? 原来stack based的VM也有其优点,就是它不对host平台的reg数量做假设,有利于移植到不同的平台。而Dalvik则不关心这些,因为它本来就是为ARM这样的多reg平台设计的。另外Dalvik被移植到x86也说明,即使是x86这种reg很少的平台,reg based的VM也是没有问题的。
下面着重说下DVM的优势:(部分文字我加黑以突出)
1、在编译时提前优化代码而不是等到运行时
2、 虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。
3、常量池已被修改为只使用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的比较:网上一些文章在讨论
Dalvik 时,大都简单提及 Dalvik 执行速度比 JVM 快,但移植性稍差。这里 我们延伸探讨一下。在一个解释器上执行 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共享一块内存区域,大大节省了内存开销。
=============================分割线===========================
下面我以我的认知来简单总结描述一下,DVM和JVM这种架构上的差异所产生的影响
JVM其核心目的,是为了构建一个真正跨OS平台,跨指令集的程序运行环境(VM)。DVM的目的是为了将android OS的本地资源和环境,以一种统一的界面提供给应用程序开发。严格来说,DVM不是真正的VM,它只是开发的时候提供了VM的环境,并不是在运行的时候提供真正的VM容器。这也是为什么JVM必须设计成stack-based的原因。
JVM:所有的jar程序,其运行环境完全是由JVM来提供,包括运行时,各类资源的调度,而JVM的架构,其设计为一个JVM里面可以运行多个java程序,JVM就像一个真正的“机器”,可以跑着多个程序。如果去看看一些企业级的JVM(例如tom cat,WAS),从OS的进程管理中,一般你只能看见一个JVM的进程(当然,你也可以起多个JVM,但JVM架构就是OS-JVM-APP的3层运行时模式),而看不见JVM里面运行的程序,而一个JVM里,可以跑多个java app。简单得说,JVM完全屏蔽了应用程序和OS之间的联系,而改用JVM充当了中间层,这也是一个真正跨平台运行时VM必须要做到的。只要是相同的JDK,JVM为所有在其中运行的程序,提供了完全一致的运行环境,而不论你是什么样的底层OS和硬件条件。因此这也是我在其他一篇答案中提到,JVM的特点是取底层OS和硬件环境的交集,从而保障这种一致性。而所有应用程序和底层资源的互动,一定是依赖JVM的传递和转换来实现。JVM真正实现了一个OS对应用程序运行时管理的所有功能。从开发环境角度和运行时角度,都是完全一致的真正VM
DVM:而DVM的特点在于使用了Zygote,Zygote有几个非常有意思的特点。
一是Zygote采用预加载,由其首先判定安装的APK的需要以及相互依存树,以及OS及硬件环境的特点,在每次启动的时候进行预加载(现在你明白为什么android的app在应用管理里你能轻易查到它都调用了那些关键性的本地资源的原因了吧?),这就意味着,你安装的应用越多,Zygote的加载就越慢,一般来说你的手机启动就会越慢。另外来说,在不同的硬件环境里(例如有无GPS芯片)Zygote初始化的实例是不同的。也就是说,zygote并不提供一个统一的运行环境,具有更好的弹性,这种机制意味着DVM可以取底层资源的合集来提供上层应用使用,差别只是在程序安装或者启动的过程中,DVM可以提示程序需求资源,本地环境可能未能满足而导致无法运行。DVM的Zygote并不是提供一个运行时容器,它提供的只是一个用于共享的进程,所有的应用程序运行,都是独立的,OS级别的进程,直接受到OS层面的资源控制以及调度的影响,只是他们共享Zygote说预加载的类而已。这也就是我为什么说,DVM就像是给每个应用程序在底层加了个套子,而不是提供了一个真正的运行时的VM。也就是说,DVM在开发环境中说提供的VM平台,和运行时的环境是很有可能不一致的。开发环境中提供的VM平台,是一个各种运行时可能环境的合集。
从这点上来说,一般我们认为,JVM中的JAVA程序的崩溃,最多导致JVM的崩溃,而不会导致OS崩溃,但是apk的崩溃,可以直接导致OS崩溃,android手机会因为应用程序死机,大家应该是很常见了。但是大家一般是不会看到java程序导致死机吧?因为运行时中间隔着一个JVM。(当然,其实还是有些小门道可以用java程序让OS崩溃,因为这个,我和某些JAVA大拿打赌赢过饭局,呵呵,不过这是其他话题,不在这里展开了)
除此之外,在JVM的机制中,不同的程序,打包以后,他们都是在运行层级真正独立的程序(指程序应用他们相互之间的关系,而不是和JVM的关系),即便他们在包里使用了同样的类,运行时都是单独加载,单独运行的(及加载多遍)。
DVM这种预加载-共享的机制,使得不同应用之间,在运行时,是共享相同的类的,一般来说,在系统资源消耗方面,拥有更高的效率。
最后,补充一点,byte code并不意味着就是解释执行,也能是加载编译,安装编译,预编译等等。实际上,不同的byte code的程序,不同的技术,不同的具体语言,其真正执行的情况是挺复杂,难以一概而论的,好多都是混合技术的案例,从我对odex的技术来看,就是个典型案例。当然这是题外话,不多展开了
Dalvik 虚拟机和 Sun JVM 在架构和执行方面有什么本质区别?的更多相关文章
- 小师妹学JVM之:JVM的架构和执行过程
目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...
- Android Dalvik 虚拟机
简介 Android 平台虽然是使用java语言来开发应用程序,但Android程序却不是运行在标准java虚拟机上的.谷歌专门为Android平台设计了一套虚拟机来运行Android程序.它就是Da ...
- Dalvik虚拟机的运行过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8914953 在前面一篇文章中,我们分析了Dal ...
- Dalvik虚拟机和JVM的对比
Dalvik虚拟机与Java虚拟机有着很多相似的特性,都支持GC,JIT,JNI等等.其主要区别在于文件格式以及指令集不同,下面对两者的特性进行比较与讨论. Difference1:文件格式 Dalv ...
- Dalvik 虚拟机 jvm 区别
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha dalvik 基于 寄存器, jvm基于 栈. 寄存器,编译时间会更短. dalvik ...
- 转 Android Dalvik虚拟机初识
首先,让我们来思考下面几个问题: 什么是Dalvik虚拟机? Dalvik VM与JVM有什么区别? Dalvik VM有什么新的特点? Dalvik VM的架构是怎么样的? 首先,我得承认第一个问题 ...
- Android Dalvik虚拟机初识(转)
原文地址:http://blog.csdn.net/andyxm/article/details/6126907 android虚拟机jvmjava优化linux内核 首先,让我们来思考下面几个问题: ...
- Android(java)学习笔记156:Java虚拟机和Dalvik虚拟机的区别
Google于2007年底正式发布了Android SDK, 作为 Android系统的重要特性,Dalvik虚拟机也第一次进入了人们的视野.它对内存的高效使用,和在低速CPU上表现出的高性能,确实令 ...
- Dalvik虚拟机
Dalvik虚拟机是google专门为android平台开发的一个java虚拟机,但它并没有使用JVM规范.Dalvik虚拟机主要完成对象生命周期的管理.线程管理.安全和异常管理以及垃圾回收等重要功能 ...
随机推荐
- BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏
Time Limit: 5 Sec Memory Limit: 162 MB Submit: 957 Solved: 394 [Submit][Status][Discuss] Description ...
- webpack 处理图片文件
1. 安装 file-loader html-loader npm install file-loader html-loader --save-dev 其中html-loader生效需配合 html ...
- crontab定时任务语法及应用
https://mp.weixin.qq.com/s/Oi9hppNQMeFiQo9s-ge79A crond 是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows ...
- 获取请求header的各种方法
部分代码非原创 不定期更新 PHP function get_all_header() { // 忽略获取的header数据.这个函数后面会用到.主要是起过滤作用 $ignore = array(' ...
- 新增对象Products 的流程说明
库内新增对象Products 的流程说明: 第一步: com.jeecms.cms.entity.assist.base下建立模型基础类,BaseCmsProducts.java com.jeecms ...
- hibernate4一对多关联多方多写一次外键导致无法创建java.lang.NullPointerException以及Cannot add or update a child row: a foreign key constraint fails
一篇文章里边有多张图片,典型的单向一对多关系 多方 当程序运行到这一句的时候必然报错 但是参考书也是这样写的 其中em是 EntityManager em = JPA.createEntityMana ...
- hashMap 源码解读理解实现原理和hash冲突
hashMap 怎么说呢. 我的理解是 外表是一个set 数组,无序不重复 . 每个set元素是一个bean ,存着一对key value 看看代码吧 package test; import jav ...
- 修改CentOS6.5主机名引起MySQL5.6.35服务问题
本来是心血来潮修改CentOS6.5的主机名 /****** 修改CentOS6.5默认主机名 ******/ .备份系统网络配置文件 [root@localhost ~]# cp /etc/sysc ...
- jmeter参数化之用户自定义变量
1. 用badboby进行录制,录制完成后保存,用JMeter格式进行保存,如:登陆.jmx 2. 在jmeter中打开保存的文件登陆.jmx. 3.线程组右击-添加-配置元件-用户定 ...
- Octave 软件的安装
每次安装软件都感觉是一种心痛的历程.下载安装,然后就跳出一堆的错误,之后就各种百度求救,然后就搞了大半天,有时候还搞不定. 最后,搞定的时候发现,原来这么简单,结果时间就这样浪费了,所以还是把这个过程 ...