Android中的ClassLoader与热修复
一:Android中有哪几种ClassLoader?他们的作用和区别是什么?
什么是ClassLoader
ClassLoader类加载器。每个java程序都是由class类组成的,只有把这些class类加载到JVM中,程序才能够运行。那么,用来加载这些类的就是ClassLoader类加载器。
Android中有哪几种ClassLoader?
ClassLoader直接实现的子类有BaseDexClassLoader和SecureClassLoader
![](https://img.haomeiwen.com/i4322600/eaececf14b50afd5.png)
而BaseDexClassLoader的子类又有如下几个:
PathClassLoader、DexClassLoader、InMemoryDexClassLoader
![](https://img.haomeiwen.com/i4322600/d56bf3213f671a78.png)
SecureClassLoader有一个子类:URLClassLoader,只能用来加载jar文件(Android平台用不了?)
![](https://img.haomeiwen.com/i4322600/65f136d30b8f3db7.png)
PathClassLoader
在应用启动时创建,用来加载app安装路径下的apk文件。
PathClassLoader有两个构造方法
![](https://img.haomeiwen.com/i4322600/3f11c74af79d829c.png)
对应参数的含义:
- dexPath:String类型;代表包含dex的jar或者apk文件路径集
- libraryPath:String类型;代表包含C、C++库的路经集合
- parent:代表PathClassLoader的父类,遵从双亲委托模型
DexClassLoader
加载SD卡上的class.dex、jar、或apk文件。
DexClassLoader有一个构造方法:
![](https://img.haomeiwen.com/i4322600/fb96aae70acb0560.png)
对应参数的含义:
- dexPath:String类型 ;包含class.dex、jar、apk的文件路径集
- optimizedDirectory:String类型;用来缓存需要加载的dex文件,并创建一个DexFile对象,如果为null,会直接使用dex文件原有路径创建DexFile;
这个参数已经弃用,自API26起无效; - librarySearchPath:String类型;包含C、C++库,可以为空;
- parent:DexClassLaoder的父类加载器,遵守双亲委托模型
InMemoryDexClassLoader
从内存中直接加载class
有两个构造函数
![](https://img.haomeiwen.com/i4322600/3e2db10eb471e8d0.png)
其中
- dexBuffers: ByteBuffer数组;包含buffer.position 和 buffer.limit之间的dex文件缓存数组
- dexBuffer:包含buffer.position 和 buffer.limit之间的dex文件
- parent:其父类,遵守双亲委托机制
URLClassLoader
从指向JAR文件和目录的URL的搜索路径加载类和资源。
区别
PathClassLoader:只能加载系统中已经安装过的apk
DexClassLoader:能够加载未安装的jar/apk/dex
InMemoryDexClassLoader:加载缓存中的dex文件或文件集
URLClassLoader:从指向JAR文件和目录的URL的搜索路径加载类和资源。
二、简述双亲委托模型
第一步:源ClassLoader 先判断该class是否已经加载,如果已经加载,则返回该class;没有加载则委托其父类加载;
![](https://img.haomeiwen.com/i4322600/83af51aa09eae316.png)
第二步:父类加载器判断是否加载过该class,如果已经加载,返回该class;如果没有加载,委托祖父类加载器;
![](https://img.haomeiwen.com/i4322600/cbe31ee568713bfd.png)
第三步:祖父类加载器判断是否加载过该class,如果加载过,返回该class;如果没有,委托始祖类加载器;
![](https://img.haomeiwen.com/i4322600/566ea213590c66e7.png)
第四步:始祖类加载器判断是否加载过该class,如果已经加载,返回class;否则委托始祖类加载器的子类加载器。
![](https://img.haomeiwen.com/i4322600/1d74c2443e5b8d16.png)
第五步:始祖类的子类(源的祖父类?)判断......
![](https://img.haomeiwen.com/i4322600/f69ba58a9d4cac63.png)
第五步:始祖类的孙类(源的父类?)判断祖先クラスローダは、クラスがロードされたかどうかを判断します。(不想写了。。。看图)
![](https://img.haomeiwen.com/i4322600/40a0efcd404c2f9c.png)
第六步:又委托给了源加载器
源Classloader说(还是扔给我了让我去加载,在心里默默说F....)
源ClassLoader去判断是否加载该class,如果已经加载,则返回class,如果没有,直接抛异常(很生气的表示老子不加载了...)
![](https://img.haomeiwen.com/i4322600/82f89d970fa61e90.png)
问题三、简述双亲委托模型在热修复领域的应用
首先,什么是热修复?
热修复就是不卸载重新安装应用的情况下,神不知鬼不觉的修改好bug。
正经的,热修复框架核心技术有三类:
- 代码修复
- 资源修复
- 动态链接库修复
那么双亲委托模型在热修复领域主要是代码修复中的类加载修复方案。
假设现在用户的手机上apk中某一个类出现了问题,现在需要去修复,使用类加载方案让ClassLoader去重新加载新的类,主要加载到了一定会返回这个类,那么有问题的类就不会被加载。但是有一个需要注意的是,这个不能及时生效,需要重启App.
代码修复还有一些其他办法:
- 类加载,双亲委托模型
- 底层替换(在native层修改原有类,反射?)
- Instant Run原理