Android热修复技术窥探

参考链接:

什么是热修复

关于热修复这个名词,并不陌生。相信大家都有过更新window补丁的经历,通过补丁可以动态修复系统的漏洞,只不过这个过程对用户而言是可选及自行操作。

Android热修复过程

那么关于Android平台的热修复技术,简单来说,就是通过下发补丁包,让已安装的客户端动态更新,让用户可以不用重新安装APP,就能够修复软件缺陷的一种技术。

随着热修复技术的发展,不仅可以修复代码,同时可以修复资源文件及SO库。

国内主流的技术方案

阿里系

名称说明
AndFix开源,实时生效
HotFix阿里百川,未开源,免费、实时生效
Sophix未开源,商业收费,实时生效/冷启动修复

HotFix是AndFix的优化版本,Sophix是HotFix的优化版本。目前阿里系主推是Sophix。

腾讯系

名称说明
Qzone超级补丁QQ空间,未开源,冷启动修复
QFix手Q团队,开源,冷启动修复
Tinker微信团队,开源,冷启动修复。提供分发管理,基础版免费

其他

名称说明
Robust美团, 开源,实时修复
Nuwa大众点评,开源,冷启动修复
Amigo饿了么,开源,冷启动修复

方案对比

方案对比SophixTinkernuwaAndFixRobustAmigo
类替换yesyesyesnonoyes
So替换yesyesnononoyes
资源替换yesyesyesnonoyes
全平台支持yesyesyesnoyesyes
即时生效同时支持nonoyesyesno
性能损耗较少较小较大较小较小较小
补丁包大小较小较大一般一般较大
开发透明yesyesyesnonoyes
复杂度傻瓜式接入复杂较低复杂复杂较低
Rom体积较小Dalvik较大较小较小较小
成功率较高较高一般最高较高
热度
开源noyesyesyesyesyes
收费收费(设有免费阈值)收费(基础版免费,但有限制)免费免费免费免费
监控提供分发控制及监控提供分发控制及监控nononono

修复原理

目前市面上很多热修复方案都是参考了instant Run的实现,instant Run的出现也是推动热修复浪潮的原因。

Android热修复方案

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热修复方案接入非常简单,总共只需要完成两个步骤(其实也是两行代码):

  1. 初始化
  2. 请求补丁

对于开发者而言,热修复只不过是一个sdk的接入,开发过程是无感的。最后使用工具提取出两个apk的差异(也就是补丁)上传修复即可。