Dalvik虚拟机简介及架构级移植优化方向
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
LOGO
5、Dalvik虚拟机核心——执行引擎
java语言是解释型语言,它是以跨平台换取执行效率为代价的。跨平台性体 现在编译的跨平台性和运行跨平台性。编译的跨平台体现在源程序不限制于 在某一平台进行编译,运行的跨平台性体现在编译出来的可执行程序也不限 制于在某一平台上运行。这样神奇是特性是不是特别具有吸引力呢? 现在我们把重点放在运行的跨平台性。运行的跨平台性是以牺牲虚拟机的平 台性相关性为代价的,而这正是我们需要解决的问题,因为官方并未提供 unicore架构的虚拟机。 Dalvik虚拟机的平台相关性集中的体现在的执行引擎上,它是Dalvik虚拟机的 核心部分,Dex字节码就是在这个部分解释执行 。 平台相关性问题我们先暂且搁置,因为在下一部分会重点分析Dalvik虚拟机 的移植。先来了解一下解释器是怎么工作的:
DEX字节码的生成过程将在后续的专有工具介绍中给出。 字节码的生成过程将在后续的专有工具介绍中给出。
LOGO
3、 Dalvik虚拟机源码目录简析
通过以上的介绍,我们对Dalvik VM能实现的功能以及为什么需要这么一个 虚拟机有了初步的认识。观其内部,Android VM的架构是什么样子的呢? 在源码中,Dalvik VM相关的内容在Android中是一个独立的代码路径: dalvik/,其中包含了目标机和主机的内容。其主要的目录如下所示: Dalvik/ |--Dx |--Vm | |--Arch | --Mterp | --Native | --Compiler |--Dalvikvm Dalvik/dx目录的内容是dx工具库,其最终将 dx专有工具(可执行文件)。另外与dx目录 同级的文件夹dexdump、tools同样对应几 个专有工具。 Dalvik/vm目录的内容是虚拟机核心实现, 其最终将生成libdvm.so(Dalvik虚拟机)。 Davlik /dalvikvm目录中的内容是虚拟机的入 口程序,会生成dalvilvm可执行程序。
LOGO
DEX文件的生成: Android系统和Dalvik虚拟机提供了工具(DX) 在把Java源代码编译成 CLASS文件后 使用DX工具 DEX文件的结构相对于.jar更加紧凑 但是为了 获得高效率我们还得进一步对.dex进行优化。
LOGO
JVM的字节码主要是零地址形式的,概念上说JVM是基于栈的架构。Google Android平台上的应用程序的主要开发语言是Java,通过其中的Dalvik VM来运 行Java程序。为了能正确实现语义,Dalvik VM的许多设计都考虑到与JVM的 兼容性;但它却采用了基于寄存器的架构,其字节码主要是二地址/三地址的 混合形式。 基于栈与基于寄存器的架构,谁更快?现在实际的处理器,大多都是基于寄存 器的架构,从侧面反映出基于寄存器比基于栈的架构更与实际的处理器接近。 但对于VM来说,源架构的求值栈或者寄存器都可能是用实际机器的内存来模 拟的,所以性能特性与实际硬件又有不同。一般认为基于寄存器架构的Dalvik VM比基于栈架构JVM执行效率更高,原因是:虽然零地址指令更紧凑,但完 成操作需要更多的load/store指令,也意味着更多的指令分派(instruction dispatch)次数与内存访问次数;访问内存是执行速度的一个重要瓶颈,二地 址或三地址指令虽然每条指令占的空间较多,但总体来说可以用更少的指令完 成操作,指令分派与内存访问次数都较少。 我们从下面的截图可以明了的看到与同一段Java代码对应的Java bytecode 与 Dalvid bytecode的比较。
对应的C实现是:
HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0) OP_END #define OP_END }
LOGO
对应的C实现是:
#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) HANDLE_OPCODE(_opcode /*vA, vB*/) vdst = INST_A(inst); vsrc1 = INST_B(inst); ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); if (_chkdiv != 0) { s4 firstVal, secondVal, result; firstVal = GET_REGISTER(vdst); secondVal = GET_REGISTER(vsrc1); if (secondVal == 0) { EXPORT_PC(); dvmThrowException("Ljava/lang/ArithmeticException;", "divide by zero"); GOTO_exceptionThrown(); } if ((u4)firstVal == 0x80000000 && secondVal == -1) { if (_chkdiv == 1) result = firstVal; /* division */ else result = 0; /* remainder */ } else { result = firstVal _op secondVal; } SET_REGISTER(vdst, result); } else { SET_REGISTER(vdst, (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); } FINISH(1); \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
LOGO
由于Dalvik中许多代码直接来源于Apache Harmony项目,因此,通过了解 Apache Harmony项目对我们认识DalvikVM有很大的帮助。 Apache Harmony技术架构如下所示:
LOGO
LOGO
4、Dalvik虚拟机专有工具的功能及使用
Dalvik的虚拟机专有工具的功能其实很简单:改造并优化java字节码。 一般来说,启动一个Dalvik虚拟机需要启动一个Android应用程序来完成,其实我 们可以直接使用Dalvik虚拟机: dx工具可以单独剥离出来使用。如,我们在pc上用java编译器把java源码编译成 class字节码(这个步骤也可以在Linux服务器上完成),然后在linux上直接使用 dx把该class字节码变成dex字节码(可以通过dx直接生成打包好的DEX格式的文 件,如.jar等),如下有一个简单 例子: % echo 'class Foo {'\ > 'public static void main(String[] args) {'\ > 'System.out.println("Hello, world"); }}' > Foo.java % javac Foo.java % dx --dex --output=foo.jar Foo.class % adb push foo.jar /sdcard % adb shell dalvikvm -cp /sdcard/foo.jar Foo
Android Dalvik 虚拟机 初识及架构简析
LO Dalvik虚拟机与Java虚拟机的区别 Dalvik虚拟机源码目录简析 Dalvik虚拟机专有工具的功能及使用 Dalvik虚拟机核心——执行引擎 Dalvik虚拟机的移植及优化方向
本 节 主 要 内 容
LOGO
如Dex字节码add-int/2addr对应的架构汇编如下:
mov r22, rINST >> #8 mov r3, rINST >> #12 and r22, r22, #15 GET_VREG(r1, r3) GET_VREG(r0, r22) FETCH_ADVANCE_INST(1) add r0, r0, r1 GET_INST_OPCODE(ip) SET_VREG(r0, r22) GOTO_OPCODE(ip) @ r22<- A+ @ r3<- B @ r1<- vB @ r0<- vA @ advance rPC, load rINST @ extract opcode from rINST @ vAA<- r0 @ jump to next instruction
#define GET_VREG(_reg, _vreg) ldw _reg, [rFP+], _vreg << #2 #define FETCH_ADVANCE_INST(_count) ldh.w rINST, [rPC+], #(_count*2) #define GET_INST_OPCODE(_reg) and _reg, rINST, #255 #define SET_VREG(_reg, _vreg) stw _reg, [rFP+], _vreg << #2 #define GOTO_OPCODE(_reg) add pc, rIBASE, _reg << #6
dex字节码和标准Java的字节码(Class)在结构上的一个区别是dex字节码将多个 文件整合成一个,这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找 速度。 原来每个类文件中的常量池现在由DEX文件中一个常量池来管理。 DEX文件可以进行进一步优化。优化主要是针对以下几个方面: 1、调整所有字段的字节序(LITTLE_ENDIAN)和对齐结构中的没一个域 2、验证DEX文件中的所有类 3、对一些特定的类进行优化,对方法里的操作码进行优化
LOGO
LOGO
Dalvik字节码以16位为单元(或许叫 “双字节码”更准确 )。上面代码中 有5条指令,其中mul-int/lit8指令占2单 元,其余每条都只占1单元,共6单元 ==12字节。
Java字节码以1字节为单元。上面代 码中有11条指令,每条都只占1单元, 共11单元==11字节。
基于寄存器与基于栈的区别更详细的介绍见补充文档。 基于寄存器与基于栈的区别更详细的介绍见补充文档。
LOGO
Dalvik专有的 专有的DEX文件格式 专有的 文件格式
一个应用中会定义很多类, 编译完成后即会有很多相应 的CLASS文件,CLASS文 件间会有不少冗余的信息。 为什么弃用已有的字节 码文件(CLASS文件) 而采用新的格式呢?
LOGO
LOGO
2、 Dalvik虚拟机与Java虚拟机的区别
然而:Dalvik VM ≠Java VM I.dalvik基于寄存器,而JVM基于stack II.Dalvik执行的是特有的DEX文件格式,而JVM运行的是*.class文件格 式。 优势: 1、在编译时提前优化代码而不是等到运行时 2、 虚拟机很小,使用的空间也小;被设计来满足可高效运行 多种虚拟机实例。 3、常量池已被修改为只使用32位的索引,以简化解释器
从应用程序的执行流程来看Dalvik VM的组成部分: DX工具:由Java编 译器编译后的.class转 换成DE格式。 类加裁器:1、原始 加载器,加载native实 现的类;2、加载器 object,加载java实现 的类。(所有process 共享) 执行引擎(解释器): 根据其自身的一套指令 集对dalvik bytecode进 行解释。 另外包括在此流程中 实现的内存管理及线程 机制
2 3 4 5 6
LOGO
1、Dalvik虚拟机初识及基本特性
什么是Dalvik虚拟机?让我们从认识Java虚拟机开始: Java虚拟机(JVM)是一个虚构出来的计算机,是通过在实际的计算机上仿真 模拟各种计算机功能来实现的。它有自己完善的硬件架构(如处理器、堆栈、 寄存器等),还具有相应的指令系统。使用“Java虚拟机”程序就是为了支持 与操作系统无关、在任何系统中都可以运行的程序。 Davlik虚拟机同Java虚拟机同样是运行Java程序的虚拟机,但Davlik虚拟机具 有其独特特性: Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其 指令集基于寄存器 基于寄存器架构,执行其特有的文件格式 特有的文件格式——dex字节码来完成对象生 基于寄存器 特有的文件格式 命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它 的核心内容是实现库(libdvm.so),架构由C语言实现。依赖于Linux内核的 一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上 表现出的高性能。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机 实例,其代码在虚拟机的解释下得以执行。让我们看看Dalvik虚拟机处在 Android系统架构的什么位置:
logoandroiddalvik虚拟机初识及架构简析wwwthemegallerycomlogo嵌入式系统概述dalvik虚拟机与java虚拟机的区别dalvik虚拟机源码目录简析dalvik虚拟机专有工具的功能及使用dalvik虚拟机初识及基本特性wwwthemegallerycomlogo1dalvik虚拟机初识及基本特性什么是dalvik虚拟机