热修复概念
首先介绍下Google I/O的Instant Run提出了几个概念:
Hot swap - 热替换:无需重启Application、无需启动Activity即可更新Java方法
Warm swap - 暖替换:重启Activity可更新Android资源
Code swap - 冷替换:重启Application达到更新效果
所以,狭义上来说“热”可以理解为“应用正在跑”,在“正在跑”的时候完成“xx”操作,才可以称之为“热xx”。安卓代码要达到真正“热”更新的效果,也只有基于AOP这种技术,就是在方法级别这个粒度做替换。如果是dex级别的,由于Application会缓存加载好的类,所以必须要重启Application,只能算“冷”更新。
但是国内通常所说的“热修复”指的是不用发布apk包即可达到更新效果。让应用能够在无需重新安装的情况实现更新,帮助应用快速建立动态修复能力。
热修复 or 插件化
热修复:当线上应用出现紧急BUG,为了避免重新发版,并且保证修复的及时性而进行的一项在线推送补丁的修复方案。
插件化:一个程序划分为不同的部分,以插件的形式加载到应用中去,本质上它使用的技术还是热修复技术,只是加入了更多工程实践,让它支持大规模的代码更新以及资源和SO包的更新。
热修复的使用场景
- 在apk轻量而快速升级时
热修复是一个动态修改代码与资源的通道,适合轻量而快速的升级。 - 远端调试
热修复技术适合于远端调试方面。可根据需要对特定的用户/机型发送补丁,在android机型碎片化严重的今天,非常有助于定点修复问题。 - 数据统计
可以根据统计需要,针对同一批用户做多种测试,这时只需要替换不同的补丁即可。
热修复各种方案对比分析
目前国内比较流行的热修复方案有”QQ空间超级补丁”、”阿里AndFix”、”微信Tinker”。
阿里的开源热修复方案还有Dexposed框架,源于手淘。采用的是native hook方案,但是其不支持art,在未来是一个很大的隐患。暂时不考虑项目中采用。
看下图各种方案的对比,比较直观:
对比发现”微信Tinker”热修复方案优势相对明显,并且由于微信庞大的用户群,其兼容性方面应该很不错的。初步建议选用”微信Tinker”。
下面简单说说几大方案各自的原理~
QQ空间超级补丁
QQ空间超级补丁技术采用DEX分包方案,使用了多个DEX加载的原理。即:把bug方法修复以后,放到一个单独的DEX里,并且放在dexElements数组的最前面,让虚拟机去加载修复完后的方法。
当patch.dex中包含Test.class时就会优先加载,在后续的DEX中遇到Test.class的话就会直接返回而不去加载,这样就达到了修复的目的。
微信Tinker
微信Tinker热修复技术提出了用一个提供DEX差量包,整体替换DEX的方案。主要的原理是与QQ空间超级补丁技术基本相同,区别在于不再将patch.dex增加到elements数组中,而是差量的方式给出patch.dex,然后将patch.dex与应用的classes.dex合并,然后整体替换掉旧的DEX,达到修复的目的。
阿里AndFix
这里先解释下HotFix的概念~
HotFix热修复服务机基于AndFix技术上,在产品易用性、安全性做了深度优化。除了AndFix的强大修复能力之外,提供了patch包加密校验、App安全校验、版本控制管理、加载修复的安全性等方面强大的服务。
阿里AndFix热修复技术提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启,对应用无性能消耗的目的。
这里很大的一个缺陷是,兼容性不是很好。本来热修复就是为了快速解决问题的,如果引入了一个框架在某些机型上引起了一些新的问题,就得不偿失了。但是对于修复紧急BUG这个场景,阿里AndFix的更为合适,它更加轻量,可以在不重启的情况下生效,且对性能几乎没有影响。微信Tinker、QQ空间超级补丁技术更多地把场景定位在发布小的新功能上,采用ClassLoader的模式,牺牲较高的性能代价去实现类、资源新增或替换的功能。阿里AndFix对应用本身做到无侵入,无性能损耗。
后续我们继续学习热修复技术~