Android虚拟机与ClassLoader类加载机制

发布于:2022-12-15 ⋅ 阅读:(540) ⋅ 点赞:(0)

前言

Android应用程序运行在Dalvik/ART虚拟机,并且每一个应用程序对应有一个单独的Dalvik虚拟机实例。
Dalvik虚拟机也算是一个Java虚拟机,只不过它执行的不是class文件,而是dex文件。

Android虚拟机

Dalivk虚拟机与Java虚拟机共享多不多的特性,差别在于两者执行的指令集不同,前者的指令集是基于寄存器的,而后者的指令集是基于堆栈的。
JVM与Dalvik区别

基于栈的虚拟机

对于基于栈的虚拟机来说,每一个运行时的线程,都有一个独立的栈,栈中记录了方法调用,每一次方法调用,栈中便会多一个栈帧。最顶部的栈帧称作当前栈帧,其代表着当前执行的方法。基于栈的虚拟机通过操作数栈进行所有操作
基于栈的虚拟机
更多相关知识可以参考:深入理解Java虚拟机

基于寄存器的虚拟机

寄存器
寄存器是CPU的组成部分。寄存器是有限存储容量的高速存储部件,他们可用来暂存指令、数据和位址。
寄存器
基于寄存器的虚拟机中没有操作数栈,但是有很多虚拟寄存器,其实和操作数栈相同,这些寄存器也存放在运行时栈中,本质上就是一个数组,与JVM相似,在Dalvik VM中每个线程都有自己的PC和调用栈,方法调用的活动记录以帧为单位保存在调用栈中。

与JVM相比,Dalvik虚拟机程序的指令数减少,数据移动次数也减少了,它们编译的时候,花费的时间更短。

ART虚拟机

Dalvik虚拟机执行的dex字节码,解释执行。从Android2.2版本开始,支持JIT即时编译(Just In Time),在程序运行的过程中中进行选择热点代码【经常执行的代码】进行编译和优化。

ART【Android Runtime】是在Android4.4中引入的一个开发者选项,也是Android5.0及更高版本的默认Android运行时,ART虚拟机执行的是本地机器码。Android的运行时从Dalvik虚拟机替换成ART虚拟机,并不要求开发者将自己的应用直接编译成目标机器码,APK仍然是一个包含dex字节码的文件。

ART虚拟机执行的本地机器码是从哪里来的?
Dalvik下应用安装的过程,会执行一次优化,将dex字节码进行优化生成odex文件,而ART下将应用的dex字节码翻译成本机机器码的最恰当AOT时机也就发生在应用安装的时候。ART引入了预先编译机制(Ahead Of Time),在安装时,ART使用设备自带的dex2oat工具来编译应用,dex中的字节码被编译成本地机器码

Android N的运作方式
ART使用预先编译(AOT),并且从Android N混合使用AOT编译,解释和JIT。

1.最初安装应用时不进行AOT编译(安装变快),运行过程中解释执行,对经常执行的方法进行JIT,经过JIT编译的方法将会记录到Profile配置文件中;
2.当设备闲置和充电时,编译守护进程会运行,根据profile文件对常用代码进行AOT编译。待下次运行时直接使用。

Android N的运作方式

类加载机制

ClassLoader继承关系

ClassLoader继承关系

双亲委派机制

概述:某个类加载器在加载类时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务或者没有父类加载器时,才自己去加载。

好处:
1.避免重复加载,当父类加载器已经加载了该类的时候,就没有必要子ClassLoader再加载一次;
2.`安全性考虑,防止核心API库被随意篡改。

对应源码如下:
双亲委派机制

类加载流程

类加载流程

热修复简介

PathClassLoader中存在一个Element数组,Element类中存在一个dexFile成员表示dex文件,即:APK中有X个dex,则Element数组中就有X个元素。
ClassLoader查找过程
在 PathClassLoader 中的Element数组为:[patch.dex , classes.dex , classes2.dex]。如果存在Key.class位于
patch.dex与classes2.dex中都存在一份,当进行类查找时,循环获得 dexElements 中的DexFile,查找到了
Key.class则立即返回,不会再管后续的element中的DexFile是否能加载到Key.class了。
因此实际上,一种热修复实现可以将出现Bug的class单独的制作一份fix.dex文件(补丁包),然后在程序启动时,从
服务器下载fix.dex保存到某个路径,再通过fix.dex的文件路径,用其创建 Element 对象,然后将这个 Element 对
象插入到我们程序的类加载器 PathClassLoader 的 pathList 中的 dexElements 数组头部。这样在加载出现Bug的
class时会优先加载fix.dex中的修复类,从而解决Bug。

更多热修复学习可参考:Android热修复学习


网站公告

今日签到

点亮在社区的每一天
去签到