1. Dex修复
Dex修复分为热部署底层热替换与冷部署重启
1.1 热部署底层替换
直接在native虚拟机层替换原有方法,是在原来类的基础上进行修改。
AndFix:将native虚拟机层原有的Method结构的所有成员变量替换成新函数Method结构的成员。
Sophix:将native虚拟机层原有的Method结构整体进行替换。
不适用的情况:
- 引起原有类中发生结构变化的修改
- 修复的非静态方法会被反射调用
1.2 冷部署重启
DexClassLoader -> DexPathList -> DexFile -> -> Element ->
dexElements.add(element)
当类的所有方法直接引用到的类(第一层级关系)和该类在同一个dex文件中时,类校验dvmVerifyClass就会返回true,类的accessFlags在虚拟机层会被设置CLASS_PREVERIFIED已校验标志。
如果类没被设置CLASS_PREVERIFIED,那么类的Verify操作都将在类的初始化进行。而类的Verify仅仅是在apk第一次安装执行dexopt的时候进行,但类的Verify会对类所有方法的指令都进行校验,是个稍重的过程,当加载的类多的时,整个Dex的加载过程耗时较大,所以插桩给类加载效率带来较大的影响。
2. 资源修复
2.1 Instant Run
- 构造加载了补丁资源的新AssetManager替换原有的AssetManager
- 将原有代码中所有引用到旧AssetManager的地方修改为新AssetManager
2.2 Sophix
构造一个package id不为0x7f的补丁资源包,此包只包含原有包中发生改变的资源以及新增的资源,然后在原有AssetManager的基础上,反射调用addAssetPath方法将补丁资源宝加载进去。
3. SO库修复
3.1 SO实时生效
1.Dalvik虚拟机下动态注册的native方法需实时修复,必须对so文件改名
2.静态注册的native方法的实时修复,因为无法得知so库中哪些native方法发生了变更,很难做到修复
3.对于新增动态注册的native方法,需在dex中增加相应的Java方法,否则加载so文件时报NoSuchMethodError,而增加Java方法是无法做到实时生效热修复,所以so库新增动态注册的native方法也无法做到实时生效热修复
3.2 SO冷部署重启生效
1. 通常的冷启动
用自己实现的加载SO库的接口替换System默认的加载SO库的接口。
2. Sophix的冷启动
反射注入方式将补丁SO插入到nativeLibraryDirectories/nativeLibraryPathElements数组的最前面,达到优先加载补丁SO的目的,从而实现SO修复。