频道栏目
首页 > 资讯 > 虚拟机 > 正文

Dalvik虚拟机特点以及和Java虚拟机的区别讲解

18-03-21        来源:[db:作者]  
收藏   我要投稿

1、Dalvik虚拟机与Java虚拟机区别

(1)Java程序经过编译生成的Java字节码保存在class文件中;Dalvik虚拟机运行的是Dalvik字节码,Dalvik字节码由Java字节码转换而来,并被打包到一个DEX可执行文件中。

(2)Dalvik可执行文件体积更小,DEX文件中所有类文件共享同一个常量池。

(3)Java虚拟机与Dalvik虚拟机构架不同。Java虚拟机基于栈构架(需要更多的指令分派与内存访问次数),Dalvik虚拟机基于寄存器构架,数据的访问通过寄存器间直接传递(比栈方式要快得多)。

示例:

public class Hello {
	public int foo(int a, int b) {
		return (a + b) * (a - b);
	}

	public static void main(String[] argc) {
		Hello hello = new Hello();
		System.out.println(hello.foo(5, 3));
	}
}

使用javap -c .Hello得到foo()函数的Java字节码:

public int foo(int, int);
    Code:
       0: iload_1    #int(操作类型) load(将局部变量存入Java栈) 下划线右边的数字表示操作具体的哪个局部变量(索引值从0开始计数)
       1: iload_2
       2: iadd    #从栈顶弹出两个int类型值相加并把结果压回栈顶
       3: iload_1
       4: iload_2
       5: isub    #从栈顶弹出两个int类型值相减加并把结果压回栈顶
       6: imul    #从栈顶弹出两个int类型值相乘并把结果压回栈顶
       7: ireturn    #返回一个int值

Java虚拟机的指令集被称为零地址形式的指令集,即指令的源参数和目标参数都是隐含的,它通过Java虚拟机中提供的一种数据结构“求值栈”来传递的。

每个线程执行时都有一个PC计数器和一个Java栈。

(1)PC计数器:以字节为单位记录当前运行位置距离方法开头的偏移量,且只对当前方法有效。

(2)Java栈:以帧为单位保存线程的运行状态,调用方法->压入栈,从方法返回->撤销相应的栈。每个线帧包括局部变量区,求值栈(操作栈数)和其它一些信息。

(3)局部变量区:存储方法的参数和局部变量。参数按源码中从左到右的顺序存储

(4)求值栈:保存求值的中间结果和调用别的方法参数等。

使用dexdump.exe得到foo()函数的Dalvik字节码:

  Virtual methods   -
    #0              : (in LHello;)
      name          : 'foo'
      type          : '(II)I'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 5
      ins           : 3
      outs          : 0
      insns size    : 6 16-bit code units
000198:                                        |[000198] Hello.foo:(II)I
0001a8: 9000 0304                              |0000: add-int v0, v3, v4
0001ac: 9101 0304                              |0002: sub-int v1, v3, v4
0001b0: b210                                   |0004: mul-int/2addr v0, v1
0001b2: 0f00                                   |0005: return v0

Dalvik虚拟机运行时同样为每个线程维护一个PC计数器与调用栈,这个调用栈维护一份寄存器列表,寄存器的数量在方法结构体的registers字段(本例中为5,即v0-v4)中给出。由于生成的代码指令减少了,程序执行速度会更快一些。

2、Dalvik虚拟机执行程序

Android系统构架(从底向上):Linux内核、函数库和Android运行时、应用程序框架、应用程序。Dalvik虚拟机属于Android运行时,它与一些核心库共同承担Android应用程序的运行工作。

Android系统启动流程:

(1)执行init进程。init进程首先做的是设备的初始化工作,然后读取inic.rc文件并启动系统中的重要外部程序Zygote。

(2)Zygote进程是Android所有进程的孵化器进程,其启动后首先初始化Dalvik虚拟机,然后启动system_server并进入Zygote模式,通过socket等候命令。

(3)当执行一个Android应用程序时,system_server进程通过socket方式发送命令给Zygote,Zygote收到命令后通过fork自身创建一个Dalvik虚拟机的实例来执行应用程序的入口函数。

Zygote提供三种创建进程的方法:

(1)fork(),创建一个Zygote进程

(2)forkAndSpecialize(),创建一个非Zygote进程

(3)forSystemServer(),创建一个系统服务进程

Davlik虚拟机执行的流程:

(1)loadClassFromDex()函数完成类的装载,每个类被成功解析后都会拥有一个ClassObject类型的数据结构存储在运行时环境中

(2)虚拟机使用gDvm.loadedClasses全局哈希表来存储与查询所有装载进来的类

(3)字节码验证器使用dvmVerifyCodeFlow()函数对装入的代码进行校验

(4)虚拟机调用FindClass()函数查找并装载main方法类,随后调用dvmInterpret()函数初始化解释器并执行字节码流。

3、Davlik虚拟机JIT(即时编译)

主流的JIT包含两种字节码编译方式:

(1)method方法:以函数或方法为单位进行编译。

(2)trace方法:以trace为单位进行编译。在函数中一般很少是顺序执行代码的,多数的代码都分成了好几条执行路径,其中函数的有些路径在实际运行过程中是很少被执行的,这部分路径被成为“冷路径”,执行比较频繁的路径被称为“热路径”。该方法能快速获取“热路径”代码,使用更少的时间和内存来编译。

相关TAG标签
上一篇:httpclient封装post请求和get请求
下一篇:MySQL数据库中四种常用存储引擎介绍
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站