网站平台建设合同,松岗做网站价格,余姚哪里有做淘宝网站的,西安房产网签查询官网Dalvik
Dalvik 是 Google 公司自己设计用于 Android 平台的 Java 虚拟机#xff0c;Android 工程师编写的 Java 或者 Kotlin 代码最终都是在这台虚拟机中被执行的。在 Android 5.0 之前叫作 DVM#xff0c;5.0 之后改为 ART#xff08;Android Runtime#xff09;。在整个…Dalvik
Dalvik 是 Google 公司自己设计用于 Android 平台的 Java 虚拟机Android 工程师编写的 Java 或者 Kotlin 代码最终都是在这台虚拟机中被执行的。在 Android 5.0 之前叫作 DVM5.0 之后改为 ARTAndroid Runtime。在整个 Android 操作系统中ART 位于图中红框位置。 虚拟机必须符合 Java 虚拟机规范也就是要通过 JCM(Java Compliance Kit)的测试并获得授权。但是 DVM/ART 并没有得到授权。DVM 大多数实现与传统的 JVM 相同 Android 最初是被设计用于手机端对内存空间要求较高 起初 Dalvik 目标是只运行在 ARM 架构的 CPU 上。
针对这几种情况Android DVM 有了自己独有的优化措施。
Dex 文件
传统 Class 文件是由一个 Java 源码文件生成的 .class 文件。Android 是把所有 Class 文件进行合并优化然后生成一个最终的 class.dex 文件。dex 文件去除了 class 文件中的冗余信息比如重复字符常量并且结构更加紧凑。因此在 dex 解析阶段可以减少 I/O 操作提高了类的查找速度。
实例演示
1. 创建2个 java 类 Dex1.java 和 Dex2.java
public class Dex1 {private int num 1;public int add(int i, int j) {return i j;}
}
public class Dex4 {private int num 1;private int count 0;public int add(int i) {return i num;}
} 2. 通过 javac 命令将它们编译为 .class 文件
javac Dex1.java
javac Dex2.java
3. 通过以下命令将 Dex1.class 和 Dex2.class 打包到一个 jar 文件中
jar cvf AllDex.jar Dex1.class Dex2.class
4. 使用 dx 命令将 AllDex.jar 进行优化并生成 AllDex.dex 文件
dx --dex --output allDex.dex AllDex.jar
注意: dx 命令需要配置环境变量中。
5. 通过 Android SDK 中的工具 dexdump 查看其字节码
dexdump -d -l plain AllDex.dex
结果如下 架构基于寄存器基于堆栈结构
JVM 指令集是基于栈结构来执行的Android 是基于寄存器的是在内存中模拟一组寄存器。Android 的字节码smali更多的是二地址指令和三地址指令。
DVM 字节码和 JVM 字节码的区别如下代码示例
public int add(int i, int j){return i j;
}
1. 编译为 Dex1.class 文件后add 方法的字节码如下通过4行指令完成 2. 通过 dx 命令将 Dex1.class 优化为 .dex 文件后再次查看它的 Dalvik 字节码。 add-int 指令需要3个寄存器参数v0、v1、v2这个指令会将 v2 和 v3 进行相加运算然后将结果保存在寄存器 v0 中。return 指令将结果返回。
Dalvik 通过2行指令完成。基于寄存器的指令比基于栈的指令少但基于寄存器的指令更长。二者比较如下 内存管理与回收
DVM 和 JVM 另一个显著的不同就是内存结构的区别主要体现在对堆内存的管理。Dalvik 虚拟机中将堆内存划分为两部分Active Heanp 和 Zygote Heap。如下图所示 图中的 Card Table 和 两个 Heap Bitmap 主要用来记录垃圾收集过程中对象的引用情况。
为什么要分 Zygote 和 Active 两部分
Android 系统中的第一个 Dalvik 虚拟机是由 Zygote 进程创建的而应用程序进程是由 Zygote 进程 fork 出来的。Zygote 进程是在系统启动时创建的它会完成虚拟机的初始化、库的加载、预置类库的加载和初始化等操作。
在系统需要一个新的虚拟机实例时Zygote 通过复制自身最快速的提供一个进程。另外对于一些只读的系统库所有的虚拟机实例都与 Zygote 共享一块内存区域大大减少了内存开销。如下图所示 当启动一个应用时Android 的操作系统需要为应用程序创建新的进程而这一操作是通过一种写实拷贝技术直接复制 Zygote 进程而来。这就意味着在开始的时候应用程序进程和 Zygote 进程共享了同一个用来分配内存的堆。然而当 Zygote 进程或者应用程序进程对该堆进行写操作时内存就会进行真正的拷贝操作使得 Zygote 进程和应用程序进程分别拥有自己的一份拷贝。拷贝是一件费时费力的事情因此为了尽量避免拷贝Dalvik 虚拟机将自己的堆划分为了两部分。
Zygote 进程在启动过程中创建 Dalvik 虚拟机时只有一个堆。但是当 Zygote 进程在 fork 第一个应用程序进程之前会将已经使用的那部分堆内存划分为一部分把还没有使用的堆内存划分为另外一部分。前者就称为 Zygote 堆后者就称为 Active 堆。无论是 Zygote 进程还是应用程序进程当它们需要分配对象的时候都在 Active 堆上进行。这样就可以使得 Zygote 堆尽可能少的被执行写操作可以减少执行写时拷贝的操作时间。 Dalvik 虚拟机堆
在 Dalvik 虚拟机中堆实际上就是一块匿名共享内存。Dalvik 虚拟机并不是直接管理这块匿名共享内存而是将它封装成一个 mspace交给 C 库来管理。
为什么这么做呢
因为内存碎片问题是一个通用问题不只是 Dalvik 虚拟机、 Java 堆为对象分配内存时会遇到在 C 库的 malloc 函数在分配内存时也会遇到。
Android 系统使用的 C 库 bionic使用了 Doug Lea 写的 dlmalloc 内存分配器。调用函数 malloc 的时候使用的是 dlmalloc 内存分配来分配内存。这是一个成熟的内存分配器可以很好的解决内存碎片问题。因此Dalvik 虚拟机就很机制的利用 C 库里面的dlmalloc 分配器来解决内存碎片问题。