美文网首页
Android 虚拟机与ClassLoader类加载

Android 虚拟机与ClassLoader类加载

作者: 我要离开浪浪山 | 来源:发表于2023-04-10 23:50 被阅读0次

    1、什么是Dalvik?

    Android应用程序运行在Dalvik/ART虚拟机,并且每一个应用程序对应有一个单独的Dalvik虚拟机实例。

    Dalvik也是实现了JVM规范的一个虚拟器,默认使用CMS垃圾回收器,但是与JVM运行 Class 字节码不同,Dalvik执行 Dex(Dalvik Executable Format) ——专为 Dalvik 设计的一种压缩格式。Dex 文件是很多 .class 文件处理压缩后的产物,最终可以在 Android 运行时环境执行。

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

    2、java基于栈的虚拟机

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

    e6ca41b484b22f4b4506ee676f2a43f.png

    3、Dalvik基于寄存器的虚拟机

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

    ce6ef3ed235882c7effb1e95cdf8588.png

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

    4、ART与Dalvik

    Dalvik虚拟机执行的是dex字节码,解释执行。从Android 2.2版本开始,支持JIT即时编译在程序运行的过程中进行选择热点代码(经常执行的代码)进行编译或者优化。

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

    5、ClassLoader

    任何一个 Java 程序都是由一个或多个 class 文件组成,在程序运行时,需要将 class 文件加载到 JVM 中才可以使用,负责加载这些 class 文件的就是 Java 的类加载机制。ClassLoader 的作用简单来说就是加载 class 文件,提供给程序运行时使用。每个 Class 对象的内部都有一个 classLoader 字段来标识自己是由哪个 ClassLoader 加载的。

    ClassLoader是一个抽象类,而它的具体实现类主要有:

    • 1、BootClassLoader

    用于加载Android Framework层class文件。

    • 2、PathClassLoader

    用于Android应用程序类加载器。可以加载指定的dex,以及jar、zip、apk中的classes.dex

    • 3、DexClassLoader

    用于加载指定的dex,以及jar、zip、apk中的classes.dex

    image.png

    6、双亲委托机制

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

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

    image.png

    7、类加载

    image.png

    8、热修复

    PathClassLoader 中存在一个Element数组,Element类中存在一个dexFile成员表示dex文件,即:APK中有X个dex,则Element数组就有X个元素。

    image.png

    在 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 虚拟机与ClassLoader类加载

          本文链接:https://www.haomeiwen.com/subject/efawddtx.html