JVM/Dalvik和ART的区别

转载 2016年08月28日 16:38:08

书籍:《深入剖析Tomcat》 《Java性能权威指南》

> JVM 和Dalvik虚拟机的区别
 虚拟机的多线程是通过线程切换并分配执行时间,同时一个内核在任一时刻只处理一条线程的指令 
 虚拟机栈和堆是线程共享的数据区,方法区、本地方法栈和程序计数器是线程所不能访问到的数据区
 其中数据访问的方式有两种:一种是句柄形式,引用指向句柄,句柄包含对象地址和对象类型;一种是指针,直接存储对象地址,以句柄少一步,所以访问也会快一些,而HotSpot就是用这种;前者也有一定优化,值发生改变时,引用不用变,后者要改变指针才行。
 内存异常有两种表现,一种叫OutOfMemoryError(内存溢出),请求的虚拟机扩展栈已无足够空间,分配给新对象,典型的标记-清理算法容易产品这种情况,另一种叫StackOverflowError(内存泄露),请求的栈深度超过虚拟机所允许 ,例如下标超过数据大小,一般线程不同步会引起这种状况的产生。
 算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度。)。


Dalvik 虚拟机和 Sun JVM 在架构和执行方面有什么本质区别?- https://www.zhihu.com/question/20207106

 JVM: .java -> javac -> .class -> jar -> .jar , 架构: 堆和栈的架构.
 DVM: .java -> javac -> .class -> dx.bat -> .dex , 架构: 寄存器(cpu上的一块高速缓存)。

  Dalvik与JVM的最大差别在于,前者基于寄存器架构(句柄引用),后者基于栈架构(指针引用),也就是说前者处理速度更快。另外后者采用JIT的编译方式即时编译-也叫热加载,适用于J2EE;而前者采用AOT的加载方式,提前编译,虽然加载时间变长,但运行过程流畅,适用于J2ME,而iOS也是同样的原理。
新生代:一般是指大批对象产生的快,消亡的也快;
老生代:一般是指大批对象产生后,不容易消。

    Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于编译后变大的程序来说,在它们执行的时候,花费的时间更短。
  Dalvik和Java运行环境的区别
1:Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。
2:Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
3:不同于Java虚拟机运行java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex
4:dex文件格式可以减少整体文件尺寸,提高I/o操作的类查找速度。
5:odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。
6:所有的Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的依赖操作系统的线程调度和管理机制
7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要         一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域。
8:Dalvik是由Dan Bornstein编写的,名字来源于他的祖先曾经居住过名叫Dalvík的小渔村,村子位于冰岛Eyjafjörður

  许多GC实现都是在对象开头的地方留一小块空间给GC标记用。Dalvik VM则不同,在进行GC的时候会单独申请一块空间,以位图的形式来保存整个堆上的对象的标记,在GC结束后就释放该空间。 
  dalvik是执行的时候编译+运行,安装比较快,开启应用比较慢,应用占用空间小ART是安装的时候就编译好了,执行的时候直接就可以运行的,安装慢,开启应用快,占用空间大用个比喻来说就是,骑自行车dalvik 是已经折叠起来的自行车,每次骑都要先组装自行车才能骑ART 是已经组装好的自行车,每次骑直接上车就能走人效率高在开启的时候,运行中的速度是差不多的。

> JVM,Java虚拟机

  对VM而言,先掌握规范才是最最重要和核心的事情。Class文件是理解Vm实现的关键。
 Oracle的JVM SE7官方规范:https://docs.oracle.com/javase/specs/jvms/se7/html/
所有从Java层调用JNI的线程以及从Native线程往调用Java函数的线程都需要创建一个JNIEnv。说白了,JNIEnv环境是Java和Native世界的桥梁。

深入java虚拟机笔记之虚拟机即时编译详解- http://blog.csdn.net/u012124438/article/details/73410381

JVM- http://blog.csdn.net/SEU_Calvin/article/category/6382949


  好多人觉得JDK源码太多,无从下手,经常半途而非,以我的经验来说,最好的方法是当你在项目中用到了某个类,可以利用空闲时间去研究,当然这是在感兴趣的前提下,比如简单 ArrayList 是如何实现的, StringBuilder 和 StringBuffer 有什么区别, HashMap 的实现原理,带着问题去分析,从简单的类开始循序渐进,同时在分析过程中能够用自己的语言整理出来.

Java虚拟机体系结构- http://geek.csdn.net/news/detail/238461
  在Java虚拟机内部有两种线程:守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,比如执行垃圾收集任务的线程。但是,Java程序也可以把它创建的任何线程标记为守护线程。而Java程序中的初始线程——就是开始于main()的那个,是非守护线程。 
  只要还有任何非守护线程在运行,那么这个Java程序也在继续运行。当该程序中所有的非守护线程都终止时,虚拟机实例将自动退出。假若安全管理器允许,程序本身也能够通过调用Runtime类或者System类的exit()方法来退出。
  Java虚拟机是通过某些数据类型来执行计算的,数据类型可以分为两种:基本类型和引用类型,基本类型的变量持有原始值,而引用类型的变量持有引用值。
  Java虚拟机的引用类型被统称为“引用(reference)”,有三种引用类型:类类型、接口类型、以及数组类型,它们的值都是对动态创建对象的引用。类类型的值是对类实例的引用;数组类型的值是对数组对象的引用,在Java虚拟机中,数组是个真正的对象;而接口类型的值,则是对实现了该接口的某个类实例的引用。还有一种特殊的引用值是null,它表示该引用变量没有引用任何对象。 
  在JAVA虚拟机中,负责查找并装载类型的那部分被称为类装载子系统。
  JAVA虚拟机有两种类装载器:启动类装载器和用户自定义类装载器。前者是JAVA虚拟机实现的一部分,后者则是Java程序的一部分。由不同的类装载器装载的类将被放在虚拟机内部的不同命名空间中。
  常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以它在Java程序的动态连接中起着核心的作用。
  每当启动一个新线程时,Java虚拟机都会为它分配一个Java栈。Java栈以帧为单位保存线程的运行状态。虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈和出栈。 
  本地方法本质上时依赖于实现的,虚拟机实现的设计者们可以自由地决定使用怎样的机制来让Java程序调用本地方法。 


> Dalvik,Android虚拟机

虚拟机JIT的实现原理的简要介绍- http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-simple-jits.html
Dalvik虚拟机- http://blog.csdn.net/jiazhijun/article/category/1363536

ART深度探索开篇:从Method Hook谈起- http://weishu.me/2017/03/20/dive-into-art-hello-world/

  Dalvik虚拟机的功能可以分为以下几部分:
1、进程管理:每个虚拟机都有一个进程,依赖于Zygote机制实现
2、Zygote进程管理:会fork出来一个子Zygote进程,一个SystemServer进程,一个非Zygote进程的Speciallize进程
3、类加载:先加载所有类库,然后加载字节码,放入类数据结构,供类解释器执行,如果有关联的超类、接口等也一并加载
4、内存管理:使用新老生代结合的方式,使用复制+标记-清除的算法
4、本地接口:JNI
5、反射机制:通过类结构的加载,查看、调用、修改类中的方法和属性
6、解释器:负责执行Dex字节码
7、即时编译:JIT

Dalvik是以前的,ART是Android 4.4(好像是)的时候发布的,因为Dalvik是应用运行的时候进行编译,而ART是全部编译完了再运行,效率要高很多。

  Dalvik编译的原理在于:开发者编译项目成dex,在安装时转成odex,减少了JIT时再进行字节码校验等工作;
而ART在Android4.4版本出现,相比较Dalvik的优势在于,直接将dex编译成可执行的机器码,这样加速App的运行,减少电量的消耗,用户体验更加流畅;当然劣势也是有的,App安装时比较慢,缓存文件变大;较之iOS一次开发者编译,即在用户手机运行有先天的弊端,优势在于Android热修复和动态加载方便,而IOS相对则比较古板。

 为什么Android4.4采用ART取代Dalvik非常重要?-- http://mobile.51cto.com/news-417703.htm

 Dalvik和ART运行时环境的区别-- http://blog.csdn.net/watermusicyes/article/details/50526814
 Dalvik和ART的区别-- http://www.cnblogs.com/shaweng/p/3811461.html

art和dalvik的区别?-- http://www.zhihu.com/question/29406156

深入理解Dalvik字节码指令及Smali文件- http://blog.csdn.net/dd864140130/article/details/52076515

 深入理解Android(三):Xposed详解-- http://www.infoq.com/cn/articles/android-in-depth-xposed?utm_source=articles_about_android-in-depth&utm_medium=link&utm_campaign=android-in-depth
 深入理解Android(二):Java虚拟机Dalvik-- http://www.infoq.com/cn/articles/android-in-depth-dalvik?utm_source=articles_about_android-in-depth&utm_medium=link&utm_campaign=android-in-depth
 深入理解Android(一):Gradle详解-- http://www.infoq.com/cn/articles/android-in-depth-gradle?utm_source=articles_about_android-in-depth&utm_medium=link&utm_campaign=android-in-depth

 Android为我们从ClassLoader派生出了两个类:DexClassLoader和PathClassLoader。DexClassLoader和PathClassLoader的父类是ClassLoader.
因此DexClassLoader和PathClassLoader都属于符合双亲委派模型的类加载器(因为它们没有重载loadClass方法)。也就是说,它们在加载一个类之前,回去检查自己以及自己以上的类加载器是否已经加载了这个类。如果已经加载过了,就会直接将之返回,而不会重复加载。
DexClassLoader和PathClassLoader其实都是通过DexFile这个类来实现类加载的。这里需要顺便提一下的是,Dalvik虚拟机识别的是dex文件,而不是class文件。因此,我们供类加载的文件也只能是dex文件,或者包含有dex文件的.apk或.jar文件。
  PathClassLoader是通过构造函数new DexFile(path)来产生DexFile对象的;而DexClassLoader则是通过其静态方法loadDex(path, outpath, 0)得到DexFile对象。这两者的区别在于DexClassLoader需要提供一个可写的outpath路径,用来释放.apk包或者.jar包中的dex文件。换个说法来说,就是PathClassLoader不能主动从zip包中释放出dex,因此只支持直接操作dex格式文件,或者已经安装的apk(因为已经安装的apk在cache中存在缓存的dex文件)。而DexClassLoader可以支持.apk、.jar和.dex文件,并且会在指定的outpath路径释放出dex文件。
  dx --dex --output=dynamic_temp.jar dynamic.jar
这样就生成了dynamic_temp.jar,这个jar和dynamic.jar有什么区别呢?
其实这条命令主要做的工作是:首先将dynamic.jar编译成dynamic.dex文件(Android虚拟机认识的字节码文件),然后再将dynamic.dex文件压缩成dynamic_temp.jar,当然你也可以压缩成.zip格式的,或者直接编译成.apk文件
  插件开发的过程中DexClassLoader和PathClassLoader这两个类加载器了是很重要的,但是他们也是有区别的,而且我们也知道PathClassLoader是Android应用中的默认加载器。他们的区别是:DexClassLoader可以加载任何路径的apk/dex/jar
PathClassLoader只能加载/data/app中的apk,也就是已经安装到手机中的apk。这个也是PathClassLoader作为默认的类加载器的原因,因为一般程序都是安装了,在打开,这时候PathClassLoader就去加载指定的apk(解压成dex,然后在优化成odex)就可以了。

   ClassLoader双亲委派机制能很好地解决类加载的统一性问题。对一个 Class 对象来说,如果类加载器不同,即便是同一个字节码文件,生成的 Class 对象也是不等的。也就是说,类加载器相当于 Class 对象的一个命名空间。双亲委派机制则保证了基类都由相同的类加载器加载,这样就避免了同一个字节码文件被多次加载生成不同的 Class 对象的问题。但双亲委派机制仅仅是Java 规范所推荐的一种实现方式,它并不是强制性的要求。近年来,很多热部署的技术都已不遵循这一规则,如 OSGi 技术就采用了一种网状的结构,而非双亲委派机制。


   Dalvik的类加载器:
import android.app.Activity;  
import android.content.Context;  
import android.os.Bundle;  
import android.util.Log;  
import android.widget.ListView;  
  
public class MainActivity extends Activity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
          
        Log.i("DEMO", "Context的类加载加载器:"+Context.class.getClassLoader());  
        Log.i("DEMO", "ListView的类加载器:"+ListView.class.getClassLoader());  
        Log.i("DEMO", "应用程序默认加载器:"+getClassLoader());  
        Log.i("DEMO", "系统类加载器:"+ClassLoader.getSystemClassLoader());  
        Log.i("DEMO", "系统类加载器和Context的类加载器是否相等:"+(Context.class.getClassLoader()==ClassLoader.getSystemClassLoader()));  
        Log.i("DEMO", "系统类加载器和应用程序默认加载器是否相等:"+(getClassLoader()==ClassLoader.getSystemClassLoader()));  
          
        Log.i("DEMO","打印应用程序默认加载器的委派机制:");  
        ClassLoader classLoader = getClassLoader();  
        while(classLoader != null){  
            Log.i("DEMO", "类加载器:"+classLoader);  
            classLoader = classLoader.getParent();  
        }  
          
        Log.i("DEMO","打印系统加载器的委派机制:");  
        classLoader = ClassLoader.getSystemClassLoader();  
        while(classLoader != null){  
            Log.i("DEMO", "类加载器:"+classLoader);  
            classLoader = classLoader.getParent();  
        }  
          
    }  

---------------------------------


Dalvik和ART运行时环境的区别

Dalvik和ART运行时环境的区别在此,我并没有打算深入的学习Dalvik和ART两种方式的实现原理,只是想知道他俩的区别。之前,也是零零散散的看过,并没有总结成文字。在此,总结下。Dalvik以下...

Android开发——JVM、Dalvik以及ART的区别

0. 前言Dalvik是Google公司自己设计用于Android平台的虚拟机。Dalvik经过优化,使其更适合Android平台。具体优点会在下面和JVM进行比较时说明。2014年6月谷歌I/O大会...

JAVA虚拟机、Dalvik虚拟机和ART虚拟机简要对比

简单介绍JAVA虚拟机,安卓Dalvik虚拟机和ART虚拟机,并做简单对比。

Android开发——JVM、Dalvik以及ART的区别

本文转载自:点击打开链接 Dalvik是Google公司自己设计用于Android平台的虚拟机。Dalvik经过优化,使其更适合Android平台。具体优点会在下面和JVM进行比较时...

Android开发——JVM、Dalvik以及ART的区别

0. 前言2014年6月25日,Android L 正式亮相于召开的谷歌I/O大会,Android L 改动幅度较大,谷歌将直接删除Dalvik,代替它的是传闻已久的ART。0.1 先对Dalvik以...

JVM、Dalvik及ART虚拟机的区别

Dalvik是Google公司自己设计用于Android平台的虚拟机。Dalvik经过优化,使其更适合Android平台。具体优点会在下面和JVM进行比较时说明。 2014年6月谷歌I/O大会,And...

Dalvik和JVM,Art的几点区别

1 2 3 4 5 6 7 Dalvik和JVM的几点区别 Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来...
  • herryy
  • herryy
  • 2015年10月26日 14:46
  • 512

JVM Dalvik ART介绍

1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算...

android Dalvik JVM ART

android Dalvik JVM ART JVM、DVM(Dalvik VM)和ART虚拟机对比 http://blog.csdn.net/evan_man/article/details...

Java Jvm、Android Dalvik和Android Art(二)——Android之路

Android dalvik我们已经知道jvm,其实jvm和dalvik虚拟机共享差不多的特性, 例如,它们都是解释执行,并且支持即时编译(JIT)、垃圾收集(GC)、Java本地方法调用(JNI)...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JVM/Dalvik和ART的区别
举报原因:
原因补充:

(最多只允许输入30个字)