〇、ClassLoader就是类加载器,作用是将编译后的class文件加载到虚拟机中,使之成为java类
一、Android中有哪几种ClassLoader?它们的作用和区别是什么?
- BootClassLoader:主要加载Android Framework层的字节码文件
- PathClassLoader:主要加载已经安装到系统中的apk文件中的字节码文件
- DexClassLoader:主要加载没有安装到系统中的apk,jar文件中的字节码文件
- BaseDexClassLoader:PathClassLoader和DexClassLoader的父类,真正实现功能的代码都在这个ClassLoader中
二、简述ClassLoader的双亲委托模型
- 首先查找当前类加载器是否加载过这个类,如果找到则返回这个类
- 如果找不到,就会调用父类的方法去查找是否加载过这个类,如果父类没有加载过就去查找祖父类加载器是否加载过,按照这样的逻辑一直查找到最上层的类加载器(始祖类加载器),因为始祖加载器没有 parent 了,就用引导类加载器去查找。
- 如果还没有找到就说明这个类 JVM 确实没有加载过,然后尝试使用引导类加载器加载这个类,如果成功则返回类,加载失败就再次尝试使用始祖类加载器,依次类推如果当前类加载器都加载失败则抛出异常
- 小结:这样做保证的类只会加载一次
三、简述双亲委托模型在热修复领域的应用
热修复的原理就是要替换类文件,
Android 的虚拟机( 基于寄存器 )与 Java 的虚拟机(基于栈)有些不同,它加载的不是 .class 字节码,而是 .dex 文件(可以通过 Google 提供的 dx 工具对 .class 文件转换得到),所以上面提到的替换类文件就是等于替换 DEX 文件。
通过 PathClassLoader 来加载我们自身 App 的 dex 文件。
通过 DexClassLoader 来加载我们的没有 BUG 补丁dex 文件。
首先通过反射拿到分别两个 ClassLoader 的 < DexPathList pathList > ( 一个是我们自己应用的,另一个是我们补丁的 )
然后再次通过反射拿到分别两个 ClassLoader 中 pathList 里面的 <Element[] dexElements > 的值。
合并两个反射到的 Element 数组。( 需要把我们的补丁 dex 中的数组放在合并的数组最前面 )
将合并的新的数组,再次通过反射重新设置到我们自身 App 的 DexPathList 中,根据双亲委托模型类加载器会首先加载没有 BUG 的类
老实交代作业我参考了https://www.jianshu.com/p/2b71f5d79595,不过我每一条都认真看了