Android虚拟机与Java虚拟机的区别
Dalvik虚拟机存在于Android系统,JVM是Java虚拟机,两者都是虚拟机,它们之间有什么区别呢?本文就对两者进行比较,讲述它们的不同。
1.定义:
Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。它可以支持已转换为.dex(即Dalvik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。(dx 是一套工具,可以将 Java .class 转换成 .dex 格式. 一个dex档通常会有多个.class。由于dex有时必须进行最佳化,会使档案大小增加1-4倍,以ODEX结尾。)
JVM:Java Virtual Mechinal(JAVA虚拟机)。JVM是JRE的一部分,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 的主要工作是解释自己的指令集(即字节码)并映射到本地的 CPU 的指令集或 OS 的系统调用。Java语言是跨平台运行的,其实就是不同的操作系统,使用不同的JVM映射规则,让其与操作系统无关,完成了跨平台性。JVM 对上层的 Java 源文件是不关心的,它关注的只是由源文件生成的类文件( class file)。类文件的组成包括 JVM 指令集,符号表以及一些补助信息。
2.区别:
(1)Dalvik 虚拟机和JVM 的第一个区别是 Dalvik 虚拟机是基于寄存器的架构(reg based),而JVM是基于栈的架构(stack based)。reg based 虚拟机的好处是可以做到更好的提前优化(ahead-of-time optimization)。 另外reg based的VM执行起来更快,但是代价是更大的代码长度,一般是1-4倍。Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个 Dalvik应用作为一个独立的Linux进程执行。
(2) 另外一个区别是Dalvik可以允许多个instance 运行,也就是说每一个Android 的App是独立跑在一个VM中.这样做的好处是一个App crash只会影响到自身的虚拟机,不会影响到其他。 Dalvik的设计是每一个Dalvik的虚拟机都是Linux下面的一个进程。那么这就需要高效的IPC。另外每一个VM是单独运行的好处还有可以动态active/deactive自己的VM而不会影响到其他VM。一个进程(所有android应用的线程都是对应一个linux线程,都运行在自己的沙盒中,不同的应用在不同的进程中运行。每个android dalvik应用程序都被赋予了一个独立的linux PID(app_*))
(3)java虚拟机运行的是java字节码。(java类会被编译成一个或多个字节码.class文件,打包到.jar文件中,java虚拟机从相应的.class文件和.jar文件中获取相应的字节码)。Dalvik运行的是自定义的.dex字节码格式。(java类被编译成.class文件后,会通过一个dx工具将所有的.class文件转换成一个.dex文件,然后dalvik虚拟机会从其中读取指令和数据)。
(4)java vm每个类都有一个常量池,DVM只有一个常量池。jvm是吧.java文本编译成.class字节码文件,在执行java程序的时候,类加载器把需要的类全部加载到内存当中去。davik虚拟机把.java文件编译成.class文件,又把.class文件转换成.dex文件,dalvik来执行.dex文件。
实际上.dex文件就是把多个class文件中的常量、方法等放到一起
在dex文件中由一个常量池管理,具体见下图
=============================分割线===========================
下面我以我的认知来简单总结描述一下,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并不意味着就是解释执行,也能是加载编译,安装编译,预编译等等。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。