笔记10DVM或ART是如何对JVM进行优化的

作者:神秘网友 发布时间:2021-01-12 20:21:30

笔记10DVM或ART是如何对JVM进行优化的

DVM大多数实现和传统的JVM相似,但是为了满足Android在手机端内存的限制,Dalvik对JVM做了一些独有的优化。

Dex文件

传统的class文件是由Java源码文件编译生成的,而Android在编译打包的时候,会将所有的class文件整合优化,最终生成class.dex文件。dex文件中去掉了class文件中的冗余信息,使得编译打包之后的class.dex文件更加紧凑,这样在ClassLoader加载解析dex文件的时候减少了I/O操作,提高了类查找的速度。

下面我们新建两个java类文件,分别是Dex1.java和Dex2.java文件:

笔记10DVM或ART是如何对JVM进行优化的

我们使用javac命令可以将java文件编译成class文件:

javac Dex1.java
javac Dex2.java

使用jar命令将两个class文件打包成一个jar包:

jar cvf AllDex.jar Dex1.class Dex2.class

上面的命令将两个class文件打包成了一个AllDex.jar的包。

最后使用dx命令将jar包优化压缩成class.dex文件:

dx --dex --output AllDex.dex AllDex.jar

打包之后的dex包,可以使用Android SDK中的dexdump工具进行查看:

dexdump -d -l plain AllDex.dex
笔记10DVM或ART是如何对JVM进行优化的

需要注意的是,Android编译打包对class文件的压缩伴随着一个副作用,就是Android的65535的问题,这一问题最直接的原因就是DVM的源代码MemberIdsSection.java中:

笔记10DVM或ART是如何对JVM进行优化的

此处规定了一个Dex文件中的方法、属性、类的个数不能超过MAX_MEMBER_IDX(65535),Android为了解决这一问题,提供了MultiDex来解决。

架构基于寄存器/基于栈结构

JVM的字节码指令的执行是基于栈进行的,而Android字节码指令的执行是基于寄存器的,这里的寄存器是在内存中模拟出的一组寄存器,而并非硬件的寄存器。Android和Java的字节码是完全不同的,Android的字节码是二地址或三地址的指令。

我们编写Dex.java文件:

笔记10DVM或ART是如何对JVM进行优化的

java文件经过javac的编译打包之后的字节码:

笔记10DVM或ART是如何对JVM进行优化的

使用dx对文件进行优化压缩之后的字节码文件:

笔记10DVM或ART是如何对JVM进行优化的

Android字节码命令说明:

add-in指令需要三个寄存器参数,这个指令会将后面两个寄存器(v2、v3)相加,然后将结果寄存在第一个寄存器(v0)中;

return指令会将最终的结果返回。

可以看到在class字节码中需要4行的指令,经过Android优化压缩之后只有2行。基于寄存器的指令明显要比基于栈的指令少,虽然指令的长度增加,但是执行的速度得到了提高。

下面是基于栈和基于寄存器指令的对比:

笔记10DVM或ART是如何对JVM进行优化的

内存管理和回收

DVM和JVM另外一个明显不同的地方就是内存结果的不同,主要体现在堆内存的划分和管理上。DVM中将堆内存分成了两部分:Active Heap和Zygote Heap。

笔记10DVM或ART是如何对JVM进行优化的

为什么要区分Zygoto Heap和Active Heap

在Android系统中,底层init进程会创建一个Zygoto进程,Zygoto创建了Android中的DVM,其他的应用进程以及SystemService也都是由Zygote进程fork出来的。

Zygote进程在被创建之后,会完成虚拟机的初始化、lib库的加载、系统资源的配置等等,当系统需要创建一个新的应用进程的时候,Zygote通过复制快速fork出一个新的进程,对于一些只读的库和资源,所有的虚拟机实例都是和Zygote共享同一块内存区域,这样大大减小了内存的开销。Android将创建的进程的堆内存划分为两块,其中一块Zygote Heap,就是为了减少相同内容的拷贝,这部分堆内存所有DVM共享,而进程自己的数据读写全部在Active Heap中进行。

笔记10DVM或ART是如何对JVM进行优化的 相关文章

  1. R语言进阶笔记5purrr替代循环

    purrr 替代循环 1 purrr循环 引用知乎张敬信的说法: ?用 R 写 「循环」 从低到高有三种境界:手动 for 循环,apply 函数族,purrr 包泛函式编程。? R写循环有三个境界: 手动for循环 apply循环 purrr泛函式编程 其中,手动for循环我最常用,apply系列半吊子

  2. R语言进阶笔记4dplyr 汇总统计

    之前写过一篇博文(汇总统计?一个函数全部搞定!),介绍R中编写一个函数,进行汇总统计。效果很不错。今天用 tidyverse 包实现一下,多角度尝试,然后尝试中学习。 1. 想要达到的效果 最近,一个朋友让我帮忙做一个图标,是这个样子的: 相关的统计参数:

  3. 【计算机网络】学习笔记第六篇:应用层(谢希仁版)

    说明: 文章主要针对科班上课做的简单笔记,以及后面针对一些面试涉及内容的详细讲解 再三声明:考研的同学好好去背书,做题,重点研究一下侧重点,加油 !!! 此文章归纳整理自:【计算机网络】(第七版)谢希仁 ,一切内容版权均归书籍作者所有,侵删 一

  4. 【计算机网络】学习笔记第五篇:运输层(谢希仁版)

    说明: 文章主要针对科班上课做的简单笔记,以及后面针对一些面试涉及内容的详细讲解 再三声明:考研的同学好好去背书,做题,重点研究一下侧重点,加油 !!! 此文章归纳整理自:【计算机网络】(第七版)谢希仁 ,一切内容版权均归书籍作者所有,侵删 一

  5. 云原生技术之docker学习笔记(2)

    // 云原生技术之docker学习笔记(2) // 今天我们看看Docker镜像相关内容。 Docker镜像说明 1、什么是Docker镜像? docker镜像是由多个文件系统叠加而成的,最底层是一个引导文件系统,也就是bootfs,用户基本上不会和底层的引导文件系统有任何交互。所以这块

  6. 云原生技术之docker学习笔记(1)

    // 云原生技术之docker学习笔记(1) // 最近的工作中,MySQL和MongoDB运维部分的内容比较少。主要工作内容都会频繁接触docker和k8s相关的内容,所以准备写写这块儿的内容。 之前的文章中,介绍过docker上部署MySQL的过程,这里贴出来链接,方便回顾: docker

  7. 云原生技术之docker学习笔记(3)

    // 云原生技术之docker学习笔记(3) // 今天我们看看Dockerfile创建的方法。 构建docker镜像,有两种方法: 1、一种是使用docker commit命令 2、另外一种是基于docker build命令和dockerfile文件 通常情况下,dockerfile构建镜像比docker commit命令构建 镜像

  8. PostgreSQL恢复进程startuphang住的原因分析一例

    简介: 最近在一个跨广域网的PostgreSQL primary standby环境中遇到一个比较奇特的问题。首先primary standby是跨广域网的,但这不是问题的重点。重点是归档也是跨光域网并且使用NFS来让standby访问归档文件。standby通过NFS获取归档,通过TCP连接primary实

  9. jQuery中Smart UI是什么

    jQuery中Smart UI是基于JQuery的Ajax开发框架,实现前、后台分离、功能和数据分离,UI层全部使用【htm+js+json】完成,通过一个统一数据接口与服务端进行数据交换。 该方法适用于所有品牌电脑 JQuery Smart UI 是基于JQuery的Ajax开发框架,实现前、后台分离

  10. 基于echarts实现3D地图的定时高亮和点击事件

    技术选型 文章所选技术栈:vue、echarts、echarts-gl 安装Vue和echarts 1、安装echarts和echarts-al npm i echarts --save npm i echarts-gl --save 2、引用echarts和echarts-gl import echarts from 'echarts';import 'echarts-gl'Vue.prototype.$echarts =

每天更新java,php,javaScript,go,python,nodejs,vue,android,mysql等相关技术教程,教程由网友分享而来,欢迎大家分享IT技术教程到本站,帮助自己同时也帮助他人!

Copyright 2020, All Rights Reserved. Powered by 跳墙网(www.tqwba.com)|网站地图|关键词