Android---DVM以及ART对JVM进行优化

news2025/2/1 11:50:16

Dalvik 

Dalvik 是 Google 公司自己设计用于 Android 平台的 Java 虚拟机,Android 工程师编写的 Java 或者 Kotlin 代码最终都是在这台虚拟机中被执行的。在 Android 5.0 之前叫作 DVM,5.0 之后改为 ART(Android Runtime)。在整个 Android 操作系统中,ART 位于图中红框位置。

虚拟机必须符合 Java 虚拟机规范,也就是要通过 JCM(Java Compliance Kit)的测试并获得授权。但是 DVM/ART 并没有得到授权。DVM 大多数实现与传统的 JVM 相同

\bullet Android 最初是被设计用于手机端,对内存空间要求较高;

\bullet 起初 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 HeanpZygote 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 分配器来解决内存碎片问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1093839.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

oracle创建数据库,导入dmp操作全家桶

背景:小明在一家IT公司就职,通过查看项目,公司使用的是oracle,几天后,经理要求他从服务器导入数据库到公司服务器,聪明的小明就开始干了起来,整理如下教程。 说明:此次演示环境oracl…

【LeetCode力扣】297. 二叉树的序列化与反序列化

目录 1、题目介绍 2、解题思路 2.1、详细过程图解 2.2、代码描述 2.3、完整代码 1、题目介绍 原题链接:297. 二叉树的序列化与反序列化 - 力扣(LeetCode) 示例 1: 输入:root [1,2,3,null,null,4,5] 输出&#…

代码随想录算法训练营第二十二天丨 二叉树part09

669. 修剪二叉搜索树 思路 递归法 从图中可以看出需要重构二叉树,想想是不是本题就有点复杂了。 其实不用重构那么复杂。 在上图中我们发现节点0并不符合区间要求,那么将节点0的右孩子 节点2 直接赋给 节点3的左孩子就可以了(就是把节点…

mac 移动硬盘推出

最近移动硬盘推出总是出现 磁盘无法推出,因为一个或多个程序正在使用它 的问题 解决办法 首先尽可能关闭所有的应用,然后点击左上角的 点击强制退出,注意其中的预览,这个通常就卡在了这里 然后就可以正常退出了

Python点击exe后报错:Failed to execute script xxxx问题的解决办法

最近工作在弄人脸识别的问题,从gitee来pull了一个但是发现报了一个Failed to execute script XXX的问题 造成这个问题的原因是执行文件exe存放的目录不对,可能在打包前exe文件并不是存在在这个位置。 解决方案将exe文件尝试存在在不同目录下&#xff…

【已解决】No Python at ‘D:\Python\python.exe‘

起因,我把我的python解释器,重新移了个位置,导致我在Pycharm中的爬虫项目启动,结果出现这个问题。 然后,从网上查到了这篇博客: 【已解决】No Python at ‘D:\Python\python.exe‘-CSDN博客 但是,按照上述…

数据结构 - 5(二叉树7000字详解)

一:二叉树的基本概念 1.1树形结构 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 注意&am…

如何删除错误堆栈里的数据

修改某个主数据。然后发现N年前,某位开发在DTP上做了一个错误堆栈。 这里面有很多历史错误信息,有几千条了,一条条删肯定不可能。 如果不删除,DTP增量无法激活,明天处理链肯定出问题。 于是找到一位印度大神的方法&a…

java劳务外包管理系统springboot+vue

当前,系统开发的技术已经发展成熟,而且通过计算机网络可以获取开发工具的使用方法,以及规范化编写的模块化代码,这些知识可以帮助开发者顺利完成本系统的编码工作。 采用JavaMysql的方式设计制作的劳务外包管理系统,在…

【Python、Qt】使用QItemDelegate实现单元格的富文本显示+复选框功能

主打一个 折磨 坑多 陪伴。代码为Python,C的就自己逐条语句慢慢改吧。 Python代码: import sys from types import MethodType from PyQt5.QtCore import Qt,QPoint,QSize,QRect,QEvent from PyQt5.QtGui import QStandardItemModel, QStandardItem,QTe…

LeetCode - 318 最大单词长度乘积(Java JS Py C)

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 318. 最大单词长度乘积 - 力扣(LeetCode) 题目描述 给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词…

关于vue3启动的一些错误总结

一、成功解决 npm ERR! ERESOLVE could not resolve 解决办法: npm i --legacy-peer-deps –legacy-peer-deps 作用: 在NPM v7中,现在默认安装peerDependencies。 在很多情况下,这会导致版本冲突,从而中断安装过程。 …

【Transformer系列】关于Transformer的若干问题FAQ解析

一、参考资料 Transformer的细节到底是怎么样的?Transformer 18问 答案解析(1)—史上最全Transformer面试题:灵魂20问帮你彻底搞定Transformer 关于Transformer的若干问题整理记录 Transformer的细节与技巧 二、FAQ Q:什么是Transformer&…

ubuntu修改IP地址

参考:ubuntu修改配置IP地址和DNS的方法总结(4种)_ubuntu设置ip地址-CSDN博客 面对ubuntu18以上的版本,主要有两种界面:图形化界面和纯命令行界面。 图形化界面配置比较简单,命令行配置稍许复杂&#xff0c…

python中的logging的使用

初级应用 import logginglogging.basicConfig(levellogging.INFO,format%(asctime)s| %(filename)s[line:%(lineno)s] |%(levelname)s| %(message)s,datefmt%Y-%m-%d %H:%M:%S,filenamesys.path[0]/running_log.log,filemodea) logging.info(This is log)高级应用 # logging的…

HTTP 响应头 X-Frame-Options

简介 X-Frame-Options HTTP 响应头用来给浏览器一个指示。该指示的作用为&#xff1a;是否允许页面在 <frame>, </iframe> 或者 <object> 中展现。 网站可以使用此功能&#xff0c;来确保自己网站的内容没有被嵌套到别人的网站中去&#xff0c;也从而避免了…

chatGPT 帮我优化mysql查询语句 优化一下查询速度

最终效果 备份一下数据库&#xff0c;加上索引就行。25ms查询完成。 对比 加上索引之前及之后的 EXPLAIN SELECT d.sn, d.imei1, d.imei2, d.remark FROM device_info_new d INNER JOIN production_log p ON d.state ‘0’ AND p.sn d.sn AND p.imei1 d.imei1 AND p.imei2 …

在雷电模拟器9上安装magisk并安装LSPosed模块以及其Manager管理器(一)

环境&#xff1a;win10 64&#xff0c;雷电模拟器9.0.60(9)&#xff0c;Android 9。 之前我都是用雷电模拟器版本4.0.78&#xff0c;Android版本7.1.2&#xff0c;为什么本篇要使用9了呢&#xff1f;先解答下这个问题。原因如下&#xff1a;经过我的测试&#xff0c;LSPosed不支…

【递归】汉诺塔问题(Java版)

目录 1.题目解析 2.讲解算法原理 2.1.如何来解决汉诺塔问题&#xff1f; 2.2.为什么这道题可以用递归来做&#xff1f; 2.2.1 什么是递归 2.2.2 为什么会用到递归 3.如何编写递归代码&#xff1f; 4.递归的细节展开图 1.题目解析 汉诺塔问题链接 在经典汉诺塔问题中&a…