• Android(java)学习笔记99:Java虚拟机和Dalvik虚拟机的区别


    Google于2007年底正式发布了Android SDK, 作为 Android系统的重要特性,Dalvik虚拟机也第一次进入了人们的视野。它对内存的高效使用,和在低速CPU上表现出的高性能,确实令人刮目相看。 依赖于底层Posix兼容的操作系统,它可以简单的完成进程隔离和线程管理。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例, 其代码在虚拟机的解释下得以执行。 
    很多人认为Dalvik虚拟机是一个Java虚拟机,因为Android的编程语言恰恰就是Java语言。但是这种说法并不准确,因为Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容;同时还要两个明显的不同:

    • Java虚拟机运行的是Java字节码,生成的字节码文件也就是class文件(class文件:二进制处理过的文件),然后再由java虚拟机去执行编译运行过程。而Dalvik虚拟机运行的则是其专有的文件格式DEX(Dalvik Executable)。
    • 在Java SE程序中的Java类会被编译成一个或者多个字节码文件(.class)然后打包到JAR文件,而后Java虚拟机会从相应的CLASS文件和JAR文 件中获取相应的字节码;Android应用虽然也是使用Java语言进行编程,但是在编译成CLASS文件后,还会通过一个工具(dx)将应用所有的 CLASS文件转换成一个.dex文件(dex文件是压缩成zip文件,这样可以减少占用空间),而后Dalvik虚拟机会从其中读取指令和数据。

    Dalvik和Android系统Android作为新一代的基于Linux的开源手机操作系统,其系统架构由下而上可以分为以下几部分:

    1)Linux内核

    2)本地库

    3)Android运行库

    4)应用框架

    5)应用    

    Dalvik VM (Android虚拟机),它可以支持已转换为.dex(即Dalvik Exacutable)格式的java应用程序。.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。

    每一个Android应用都运行在一个Dalvik VM实例里,而每一个虚拟机实例都是一个独立的进程空间。虚拟机的线程机制、内存分配和管理、Mutex等都是依赖底层操作系统实现的。所有Android应用的线程都对应一个Linux线程,虚拟机因而可以更多依赖操作的线程调度和管理机制。

       

    Java虚拟机和Dalvik虚拟机的区别

      java虚拟机 Dalvik虚拟机
      java虚拟机基于栈。 基于栈的机器必须使用指令来载入和操作栈上数据,所需指令更多更多 dalvik虚拟机是基于寄存器的
      java虚拟机运行的是java字节码。(java类会被编译成一个或多个字节码.class文件,打包到.jar文件中,java虚拟机从相应的.class文件和.jar文件中获取相应的字节码)

     

    Dalvik运行的是自定义的.dex字节码格式。(java类被编译成.class文件后,会通过一个dx工具将所有的.class文件转换成一个.dex文件,然后dalvik虚拟机会从其中读取指令和数据)
        常量池已被修改为只使用32位的索引,以 简化解释器。dalvik的堆和栈的参数可以通过-Xms和-Xmx更改
        一个应用,一个虚拟机实例,一个进程(所有android应用的线程都是对应一个linux线程,都运行在自己的沙盒中,不同的应用在不同的进程中运行。每个android dalvik应用程序都被赋予了一个独立的linux PID(app_*))

     

    Dalvik和标准Java虚拟机(JVM)之间的首要差别之一,就是Dalvik基于寄存器,而JVM基于栈Dalvik基于寄存器指令体大,但是指令不多JVM指令体小,但是指令多
    Dalvik和Java之间的另外一大区别就是运行环境——Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个 Dalvik应用作为一个独立的Linux进程执行。
    (1)虚拟机很小,使用的空间也小
    (2)Dalvik没有JIT编译器;
    (3)常量池已被修改为只使用32位的索引,以简化解释器
    (4)它使用自己的字节码,而非Java字节码

     备注:

    JIT编译器,英文写作Just-In-Time Compiler,中文意思是即时编译器
    JIT编译器能够将MSIL编译成为各种不同的机器代码,以适应对应的系统平台,最终使得程序在目标系统中得到顺利地运行

    Dalvik虚拟机架构:

      在android源码中,Dalvik虚拟机的实现位于“dalvik/”目录下,其中“dalvik/vm”是虚拟机的实现部分,将会编译成libdvm.so;而"dalvik/libdex"将会编译成libdex.a静态库作为dex工具;“dalvik/dexdump”是.dex文件的反编译工具;虚拟机的可执行程序位于“dalvik/dalvikvm”中,将会编译成dalvikvm可执行文件。

      dalvik虚拟机架构:

    Android应用编译及运行流程:

    Dalvik进程管理:

       dalvik进程管理是依赖于linux的进程体系结构的,如要为应用程序创建一个进程,它会使用linux的fork机制来复制一个进程(复制进程往往比创建进程效率更高)。

       Zygote是一个虚拟机进程,同时也是一个虚拟机实例的孵化器,它通过init进程启动。首先会孵化出System_Server(android绝大多系统服务的守护进程,它会监听socket等待请求命令,当有一个应用程序启动时,就会向它发出请求,zygote就会FORK出一个新的应用程序进程).每当系统要求执行一个android应用程序时,Zygote就会运用linux的FORK进制产生一个子进程来执行该应用程序。

       每当执行一个Android应用程序,Zygote就会孵化一个子线程去执行该应用程序系统内部执行dvz指令完成的。这样做的好处是显而易见的,Zygote进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等操作,而在系统需要一个新的虚拟机实例时,Zygote通过复制自身,最快速地提供一个系统。另外,对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域,这样可以大大节省内存开销。

       相对于基于堆栈的虚拟机实现,基于寄存器的虚拟机实现虽然在硬件通用性上要差一些,但是它在代码的执行效率却更胜一筹。在基于寄存器的虚拟机中,可以更加有效地减少多余指令的分发和减少内存的读写访问。

    JVM和Dalvik进程管理:

       linux中进程间通信的方式有很多,但是dalvik使用的是信号方式来完成进程间通信。

     

    Android的初始化流程:

     

                                                                                                                                                                                              

  • 相关阅读:
    虚函数中的变量作用域问题
    C++技能重拾2
    C++技能重拾
    位运算取第一个非0的位 r & (~(r-1))
    ThoughtWorks微服务架构交流心得
    字符串匹配的sunday算法
    Codeforces Round #270(利用prim算法)
    HDFS建筑与shell操作
    Spark SQL 源代码分析系列
    HDU 4686 Arc of Dream(递归矩阵加速)
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4731098.html
Copyright © 2020-2023  润新知