简述 Android中哪几种ClassLoader?它的作用和区别是什么?
Android 的 Dalvik/ART 虚拟机如同标准 Java 的 JVM 虚拟机一样,也是同样需要加载 class 文件到内存中来使用,但是在 ClassLoader 的加载细节上会有略微的差别。
- BootClassLoader
BootClassLoader 为ClassLoader 内部类,是用来预加载常用类的。在Zygote进程中创建。 - PathClassLoader
PathClassLoader 为ClassLoader的直接子类,在应用启动时,从data/app/...目录下加载APK文件,他的构造函数也明显遵循双亲委托模式,具体实现在父类BaseDexClassLoader里面。一般只加载已安装的apk文件 - DexClassLoader
DexClassLoader 也是BaseDexClassLoader的子类,与PathClassLoader的区别在于 它可以加载除了已安装的APK文件也可以加 载SD上的APK文件,这也是插件化与热修复的基础,在不需要安装APK的情况下,完成dex的加载
简述 ClassLoader的双亲委托模型
当类加载器收到加载类或资源的请求时,通常先会判断自己是否加载过这个请求类或资源,如果自身没有加载过则委托父类去加载,当父类的基类都没有加载过这个请求类才会在对应类的路径寻找Class字节码 载入,然后返回,如果没有则会转给子类去寻找对应类的路径,如此反复直到源ClassLoader,如果源ClassLoader也没有找到路径则会报错
具体步骤如下
- 源ClassLoader 首先判断自身是否加载过 请求类Class,如果加载过就直接返回,否则委托父类加载器
- 父类加载器也先判断自身是否加载过该Class,与源ClassLoader一样,如果加载过直接返回,没有就会委托父类的父类加载器继续这一步骤
- 依此类推,直到最上层的父类也没有加载过请求类,如果没有就会从该请求类的路径下寻找Class字节码并将文件载入,载入成功就会直接返回ClassLoader,否则会传给子类继续该动作.
- 以此内推,直到源ClassLoader 也通过请求类的路径来寻找该Class字节码做加载, 加载成功就会返回请求类的ClassLoader,失败则会报错。抛出异常
简述 双亲委托模型在热修复领域的应用
热修复的实现的一个原理就是通过BaseDexClassLoader的findClass方法 来使DexPathList的findClass方法来处理,在DexPathList的内部则会遍历DexFile,通过DexFile的dex.loadClassBinaryName来完成类的加载,所以我们只要把补丁文件放在最前面让类加载完成并返回,就不会去加载之前旧的类. 又因为BaseDexClassLoader是DexClassLoader的父类及具体实现类,当子类没有加载请求类的时候就委托父类来进行加载,所以又和我们双亲委托模式息息相关。