Android虚拟机和类加载机制

Android虚拟机和类加载机制,第1张

概述Android虚拟机和类加载机制1. JVM与DalvikAndroid应用程序运行在Dalvik/ART虚拟机,并且每个应用程序对应有单独的Dalvik虚拟机实例。Dalvik虚拟机实则也算是一个Java虚拟机,只不过他执行的不是class文件,的是dex文件。class文件是一个文件一个类,.dex文件是一个文件多个类。Da AndroID虚拟机和类加载机制1. JVM与Dalvik

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

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

那什么是基于栈的虚拟机,什么又是基于寄存器的虚拟机?

1.1 基于栈的虚拟机

​ 对于基于栈的虚拟机来说,每一个运行时的线程,都有一个独立的栈。栈中记录了方法调用的历史,每有一次方法调用,栈中便会多一个栈桢。最顶部的栈桢称作当前栈桢,其代表着当前执行的方法。基于栈的虚拟机通过 *** 作数栈进行所有 *** 作。

1.2 基于寄存器的虚拟机

器是CUP的一部分。寄存器是有限存储容量的高速存储部件,它们可以用来寄存指令,数据和位址。**

基于寄存器的虚拟机中没有 *** 作数栈,但是有很多虚拟寄存器。其实和 *** 作数栈相同,这些寄存器也存放在运行时栈中,本质上就是一个数组。与JVM相似,在Dalvik VM中每个线程都有自己的PC和调用栈,方法调用的活动记录以帧为单位保存在调用栈上

与JVM版相比,可以发现Dalvik版程序的指令数明显减少了,数据移动次数也明显减少了。

少了 进行局部变量表和栈的移动的过程,给寄存器存储,然后寄存器和cup之间计算。计算机的结果存会计数器。注意其是虚拟寄存器,也就是一块内存。

2. ART 与 Dalvik

Dalvik虚拟机执行的是dex字节码,解释执行。从AndroID 2.2版本开始,支持JIT即时编译(Just In Time)

在程序运行的过程中进行选择热点代码(经常执行的代码)进行编译或者优化。

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

那么,ART虚拟机执行的本地机器码是从哪里来?

dex2aot

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

**AndroID N的运行 *** 作 ** 7.0

ART 使用预先AOT编译,并且从AndroID N混合使用AOT编译,解释和JIT

1、最初安装应用时不进行任何 AOT 编译(安装又快了),运行过程中解释执行,对经常执行的方法进行JIT,经过 JIT 编译的方法将会记录到Profile配置文件中。

2、当设备闲置和充电时,编译守护进程会运行,根据Profile文件对常用代码进行 AOT 编译。待下次运行时直接使用。

3. ClassLoader

BootClasslader 启动的类加载

String Activity 等手机系统的类。

PathClassLoader AndroID应用程序类加载器

AppCompatActivity等第三方类 自己写的类

getClassLoader().loadClass("com.cn.joy.Dom"); // 全限定名class c = PathList.findClass(name,supressedException)

类加载过程。把dex文件的path参数传入classlodaer。持有一个dexpathList ,把这些dex文件转成数组,element里面有dexfile 调用loadclassBinaryname来找类

热修复

把补丁包插到有BUG的dexElement前面,找到了就忽视有BUGdex

怎么实现?

类没有被使用过,加入补丁包才有用,要不已经加入缓存了,直接去缓存里面找了。

启动的时候热修复

怎么加到数组里面去?

反射。

获得当前应用的PathClassloade

反射获取到DexPathList属性对象

反射修改pathList的dexElements

把补丁包的path.dex转换为Element[] (path)获得的pathList的dexElement属性(old)path+old 合并,并反射赋值给pathList的dexElements4. 双亲委托机制!

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

为什么?

1、避免重复加载,当父加载器已经加载了该类的时候,就没有必要子ClassLoader再加载一次。

2、安全性考虑,防止核心API库被随意篡改。

通过父加载器加载了系统的String类,自己写的String就不会加载,要不系统的核心代码就被修改了

总结

以上是内存溢出为你收集整理的Android虚拟机和类加载机制全部内容,希望文章能够帮你解决Android虚拟机和类加载机制所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1028303.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存