为什么需要热修复?
- 重新发版代价太大,用户更新还不及时
- bug修复不及时,用户体验差
- 插件化?那就很小的改动也要发布一个模块
- Hybrid方案?需要将经常变更的业务以H5独立出来,但是如果无法转为H5,bug还是无法修复,并且需要开发人员新增技术栈
- 热修复对用户的流量小,影响小,损失降到最低
从本质理解热修复的实现
AndroidManifest 出现bug是无法修复的,因为它是由系统进行解析的,解析过程不会访问补丁包,因此如果想要增加四大组件,通常来说是不可以直接添加的。通常的做法是预先在安装包AndroidManifest 中埋入代理的组件。
代码如何修复,所有的java代码最终都编译为 class.dex 格式文件,因此,任何的热修复方案,都需要在补丁包中包含一个新逻辑的 dex 文件,并且改变执行流,引导执行到新 dex 文件。
资源的修复,必须想办法把原油安装包替换为新的资源包,而有些资源,比如桌面图标、通知栏图标以及 RemoteView 之类的资源,是由系统直接解析安装包的资源得到的,对于这类资源,任何热修复方法都无法进行资源替换和修复。
so的修复应该是最明确的,Android 系统中所有的 so 库都是由 System.load 进行加载,因此只要找到办法在加载的时候优先加载补丁包的 so,就能够进行底层代码替换了。
发展历程
阿里最开始的 Dexposed 框架基于 Xposed 框架的 Java Method Hook 技术,但是对底层 Dalvik 结构过于依赖,最终无法继续兼容 Android 5.0 以后的 ART 虚拟机,后续作罢。
后来提出的 Andfix 同样是底层结构替换的方案,做到了 Dalvik 和 ART 环境的兼容。再者,还有基于 Andfix 阿里百川 HotFix ,但是都是基于底层固定结构,使用有很多限制,只提供代码层修复,不支持资源和so层修复。
行业内著名的还有: 腾讯空间超级补丁技术、微信的Tinker、饿了么的 Amigo、美团的 Robust等。
最终,阿里推出了 Sophix 方案,支持 代码修复、资源修复、so修复。它的核心理念就是 非侵入性。不修改打包流程,也不插入任何 AOP 代码。唯一需要的就是 初始化和请求补丁两行代码。
代码修复
代码修复主要有2大方案:
- 阿里的底层替换方案: 立即见效,加载也轻快,但是限制很多。
- 腾讯系的类加载方案:需要冷启动见效,修复范围广,限制少。