介绍
Qzone 超级补丁技术基于dex分包方案,使用了多dex加载(multidex)的原理,大致的过程就是:把BUG方法修复以后,放到一个单独的dex文件,然后插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。
该方案的灵感来源?
没错就是类加载机制,相信大部分同学都对它有所了解吧。
ClassLoader 类加载机制
Android应用程序本质上使用的是java开发,使用标准的java编译器编译出Class文件,和普通的java开发不同的地方是把class文件再重新打包成dex类型的文件,这种重新打包会对Class文件内部的各种函数表、变量表等进行优化,最终产生了odex文件。odex文件是一种经过android打包工具优化后的Class文件,因此加载这样特殊的Class文件就需要特殊的类装载器,所以android中提供了DexClassLoader类。
类图:
Android使用的是Dalvik虚拟机装载class文件,所以classloader不同于java默认类库rt.jar包中java.lang.ClassLoader, 可以看到android中的classloader做了些修改,但是原理还是差不多的。
学过java的同学都知道, 类加载器是采用双亲委派机制来进行类加载的。
双亲委托模式是什么?
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
为什么要用双亲委托模式?
- 可以避免重复加载,当父加载器已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
- 安全性考虑,防止核心API库被随意篡改。我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中的定义类型,这样会存在非常大的安全隐患。
双亲委派机制 从ClassLoader.java 源代码可以清晰的看出来:
ClassLoader.java
流程大概如下:
1.判断类是否已经加载过;
2.父类加载器优先加载;
3.parent为null,则调用BootstrapClassLoader进行加载 ;
4.如果class依旧没有找到,则调用当前类加载器的findClass方法进行加载;
BaseDexClassLoader.java
DexPathList.java