热修复技术介绍
代码修复 有两大主要方案,一种是阿里系的底层替换方案,还有一种是腾讯系的类加载方案。两类差别主要体现如下:
底层替换方案限制较多,但是时效性最好,且加载轻快
类加载方案时效性较差,需重新冷启动才能见效,但修复范围广,限制少。
底层替换方案
底层替换方案是在已经加载的类中直接替换原有方法,在原有类的基础上进行修改,因而无法实现对与原有类进行方法和字段的增减,因为这样将破坏原有类的结构。
一旦补丁类中出现了方法个数的增加或者减少,就会导致这个类及整个dex的方法个数的变化。方法个数的变化直接导致方法索引的变化,这样在访问方法时就无法索引到正确的方法了,同样,字段的增加与减少也会出现此类问题。
传统的底层替换方式,不论是 Dexposed、AndFix还是其他相关Hook底层代码方案的方式,都是直接依赖修改虚拟机方法实体的具体字段实现的。例如,修改Dalvik方法的JNI函数指针、修改类或者方法的访问权限等等。这样其实是很有风险的,因为Android系统的开源性,导致手机各厂商在对代码进行改造之后,使得原有的修复框架里的结构体不匹配,那么采用这种开源库进行修复就会在此类设备上出现问题,导致无法修复。基于此,阿里系的Hotfix以一种极其优雅的替换方式,实现了即时生效的代码热修复方案。在实现过程中,不修改底层具体结构。这里面主要涉及到底层ArtMethod结构体相关处理技术,后面继续。
类加载方案
类加载方案的原理:在APP重新启动后,让ClassLoader去加载新的类,从而替换有问题的类,达到修复目的。
这里看看腾讯系的三大类加载方案的实现原理。
Instant Run热修复方案
Instant Run资源热修复可简单地总结为【Android 8.0系统源码 - MonkeyPatcher.java】:
- (1)创建新的AssetManager,通过反射调用addAssetPath方法加载外部的资源,这样新创建的AssetManager就含有了外部资源。
- (2)将AssetManager类型的mAssets字段的引用全部替换为新创建的AssetManager.
热替换代码修复
冷启动代码修复
资源热修复技术
so库热修复技术
主流热修复框架
热修复技术前景
对于Tinker热修复这个框架来说,所做的工作很多,包括:除了编译阶段的差分异操作生成补丁文件、运行时的全量合成和动态加载、还做了大量的工作用于安全校验(MD5、CRC等等),可以参考别人的设计思想。
基于对Tinker实现原理的理解,解决Android 10.0 动态加载dex无法触发dex2oat的问题:反射了PMS的registerDexMode这个方法,强制让系统帮我们触发dex2oat这个优化操作