(1)原理
- Android Dex打包原理
1、打包apk的时候,会把java文件通过类加载器编译成class文件,然后把class文件组合成class.dex文件,目的是把不同class文件重复的东西只需保留一份
2、dex文件会把每一个类的id检索起来,存在一个链表里面,这个链表的长度是用short类型存储的,最大值是65536,也就是单个dex文件的方法数上限为65536。方法数包括引用的framwork方法,library方法,还有自己写的代码方法。
3、因为在生成.dex文件之后会生成一些多余的资源,所以系统会对dex文件进行优化,会分配一个缓冲区,缓冲区大小的限制:在android2.x的系统上缓冲区只有5MB,android4.x为8MB或者16MB,如果方法数量超过缓冲区的大小时,会造成dexopt崩溃,所以我们一般apk的方法数要控制在65536以内,如果超出,就要考虑dex分包,api14(Android5.0)之前是不支持分包的
- Android虚拟机类加载机制
1、Android虚拟机内部使用BaseDexClassLoader/PathClassLoader/DexClassLoader三个类加载器实现(和Java的类加载器不是一个东西),从DEX文件中读取数据,其中PathClassLoader/DexClassLoader继承自BaseDexClassLoader实现的
2、dex文件转换成dexFile对象,存入Element[]数组,findclass顺序遍历Element数组获取DexFile,然后执行DexFile的findclass
// 加载名字为name的class对象
public Class findClass(String name, List<Throwable> suppressed) {
// 遍历从dexPath查询到的dex和资源Element
for (Element element : dexElements) {
DexFile dex = element.dexFile;
// 如果当前的Element是dex文件元素
if (dex != null) {
// 使用DexFile.loadClassBinaryName加载类
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
if (dexElementsSuppressedExceptions != null) {
suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
}
return null;
}
- 类加载热修复
1、当分包完成之后,会形成一个dex包的有序数组,当需要加载类加载器的时候,会从数组中第一个dex包开始加载,直到找到这个类为止,当多个dex包中都有这个文件的时候,就取第一个文件
2、热修复是通过将已经修复了的bug包打成dex包,并将这个dex包放在有序数组的第一个,当加载类文件的时候,首先会找到修改好的dex包去替换之前存在bug的dex包