参考链接:
- [1] . 《Android热修复技术,你会怎么选?》
- [2] . 《Android热修复技术选型——三大流派解析》
- [3] . 《阿里云热修复使用文档》
- [4] . 《热修复——深入浅出原理与实现》
- [5] . 《Android Hook技术防范漫谈》
- [6] . 《深入探索Android热修复技术原理》
什么是热修复
关于热修复这个名词,并不陌生。相信大家都有过更新window补丁的经历,通过补丁可以动态修复系统的漏洞,只不过这个过程对用户而言是可选及自行操作。
那么关于Android平台的热修复技术,简单来说,就是通过下发补丁包,让已安装的客户端动态更新,让用户可以不用重新安装APP,就能够修复软件缺陷的一种技术。
随着热修复技术的发展,不仅可以修复代码,同时可以修复资源文件及SO库。
国内主流的技术方案
阿里系
名称 | 说明 |
---|---|
AndFix | 开源,实时生效 |
HotFix | 阿里百川,未开源,免费、实时生效 |
Sophix | 未开源,商业收费,实时生效/冷启动修复 |
HotFix是AndFix的优化版本,Sophix是HotFix的优化版本。目前阿里系主推是Sophix。
腾讯系
名称 | 说明 |
---|---|
Qzone超级补丁 | QQ空间,未开源,冷启动修复 |
QFix | 手Q团队,开源,冷启动修复 |
Tinker | 微信团队,开源,冷启动修复。提供分发管理,基础版免费 |
其他
名称 | 说明 |
---|---|
Robust | 美团, 开源,实时修复 |
Nuwa | 大众点评,开源,冷启动修复 |
Amigo | 饿了么,开源,冷启动修复 |
方案对比
方案对比 | Sophix | Tinker | nuwa | AndFix | Robust | Amigo |
---|---|---|---|---|---|---|
类替换 | yes | yes | yes | no | no | yes |
So替换 | yes | yes | no | no | no | yes |
资源替换 | yes | yes | yes | no | no | yes |
全平台支持 | yes | yes | yes | no | yes | yes |
即时生效 | 同时支持 | no | no | yes | yes | no |
性能损耗 | 较少 | 较小 | 较大 | 较小 | 较小 | 较小 |
补丁包大小 | 小 | 较小 | 较大 | 一般 | 一般 | 较大 |
开发透明 | yes | yes | yes | no | no | yes |
复杂度 | 傻瓜式接入 | 复杂 | 较低 | 复杂 | 复杂 | 较低 |
Rom体积 | 较小 | Dalvik较大 | 较小 | 较小 | 较小 | 大 |
成功率 | 高 | 较高 | 较高 | 一般 | 最高 | 较高 |
热度 | 高 | 高 | 低 | 低 | 高 | 低 |
开源 | no | yes | yes | yes | yes | yes |
收费 | 收费(设有免费阈值) | 收费(基础版免费,但有限制) | 免费 | 免费 | 免费 | 免费 |
监控 | 提供分发控制及监控 | 提供分发控制及监控 | no | no | no | no |
修复原理
目前市面上很多热修复方案都是参考了instant Run的实现,instant Run的出现也是推动热修复浪潮的原因。
NativeHook 原理
NativeHook的原理是直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能。
优点:
- 即时生效
- 没有性能开销,不需要任何编辑器的插桩或代码改写
缺点:
- 存在稳定及兼容性问题。ArtMethod的结构基本参考Google开源的代码,各大厂商的ROM都可能有所改动,可能导致结构不一致,修复失败。
- 无法增加变量及类,只能修复方法级别的Bug,无法做到新功能的发布
javaHook 原理
打基础包时插桩,在每个方法前插入一段类型为 ChangeQuickRedirect 静态变量的逻辑,插入过程对业务开发是完全透明。加载补丁时,从补丁包中读取要替换的类及具体替换的方法实现,新建ClassLoader加载补丁dex。当changeQuickRedirect不为null时,可能会执行到accessDispatch从而替换掉之前老的逻辑,达到fix的目的。
优点:
- 高兼容性(Robust只是在正常的使用DexClassLoader)、高稳定性,修复成功率高达99.9%
- 补丁实时生效,不需要重新启动
- 支持方法级别的修复,包括静态方法
- 支持增加方法和类
- 支持ProGuard的混淆、内联、优化等操作
缺点
- 代码是侵入式的,会在原有的类中加入相关代码
- so和资源的替换暂时不支持
- 会增大apk的体积,平均一个函数会比原来增加17.47个字节,10万个函数会增加1.67M
java mulitdex 原理
Android内部使用的是BaseDexClassLoader、PathClassLoader、DexClassLoader三个类加载器实现从DEX文件中读取类数据,其中PathClassLoader和DexClassLoader都是继承自BaseDexClassLoader实现。dex文件转换成dexFile对象,存入Element[]数组,findclass顺序遍历Element数组获取DexFile,然后执行DexFile的findclass。
优点:
- 不需要考虑对dalvik虚拟机和art虚拟机做适配
- 代码是非侵入式的,对apk体积影响不大
缺点:
- 需要下次启动才修复
- 性能损耗大,为了避免类被加上CLASS_ISPREVERIFIED,使用插桩,单独放一个帮助类在独立的dex中让其他类调用。
dex替换
为了避免dex插桩带来的性能损耗,dex替换采取另外的方式。原理是提供dex差量包,整体替换dex的方案。差量的方式给出patch.dex,然后将patch.dex与应用的classes.dex合并成一个完整的dex,完整dex加载得到dexFile对象作为参数构建一个Element对象然后整体替换掉旧的dex-Elements数组。
优点:
- 兼容性高
- 补丁小
- 开发透明,代码非侵入式
缺点:
- 冷启动修复,下次启动修复
- Dex合并内存消耗在vm head上,容易OOM,最后导致合并失败
阿里热修复–Sophix
阿里的Sophix热修复方案接入非常简单,总共只需要完成两个步骤(其实也是两行代码):
- 初始化
- 请求补丁
对于开发者而言,热修复只不过是一个sdk的接入,开发过程是无感的。最后使用工具提取出两个apk的差异(也就是补丁)上传修复即可。