Android 热修复 - 各框架原理学习及对比

转载请注明出处:https://www.jianshu.com/p/2eae8a69eb27

写在开头

从15年开始各技术大佬们开始研究热修复技术,并陆续开源了许多的热修复框架。如 Jasonross 的 Nuwa,美团的 Robust,阿里的 Andfix,腾讯的 Tinker 等等...均是Android 前辈们夜以继日的成果。而现在热修复被广泛地应用于Android 应用和游戏,运用并理解热修复框架在面试中也是加分项。所以,赶紧学起来吧...

本文以Tinker 作为学习对象,主要讲述各开源框架的对比和记录Tinker 的Demo 集成过程。

热修复框架原理总结

这一节篇幅较长,主要是用自己的话来总结各热修复框架的实现原理。如果想看Tinker接入实现的同学可进入下一章节。Android 热修复 - Tinker 实现及踩过的坑

Nuwa 实现原理:

最早看到热修复框架的相关文章就是Qzone官方的文章,但是Qzone热修复技术的实现代码并没有开源。不过GitHub上有一开源的热修复框架Nuwa,实现原理和其相似。这里我们以Qzone为例进行分析。

Qzone的实现原理是生成差分dex文件,将patch.dex插到dexElements的最前面。但patch.dex中的类patchA.java会引用classes.dex中的类classesB.java,如果这两个类所在的patch.dex和classes.dex不是同一个文件就会报错。

疑惑的Qzone技术大佬发现classes.dex和classes2.dex也不是同一个文件,为啥不报错?于是继续查,发现了这个判断

if(!fromUnverifiedConstant && IS_CLASS_FLAG_SET(referrer, CLASS_ISPREVERIFIED)){

如果被引用者(也就是classesB.java)这个类被打上了CLASS_ISPREVERIFIED标志,那么就会进行dex的校验。校验不过就报错了。

那么这个标志是什么时候被打上去的?
在apk安装的时候,虚拟机会将dex优化成odex后才拿去执行。在这个过程中会对所有class进行校验。

怎么校验的?
假设classesB.java类在它的static方法,private方法,构造函数,override方法中直接引用到classesC.java类。如果classesB.java类和classesC.java类在同一个dex中,那么classesB.java类就会被打上CLASS_ISPREVERIFIED标记,被打上这个标记的类不能被其他dex中的类引用,否则就会报错。所以要防止类被打上CLASS_ISPREVERIFIED的标志。

如何防止类被打上CLASS_ISPREVERIFIED的标志?
Common类会被打包成单独的hack.dex,这样当安装apk的时候,classes.dex内的类都会引用一个在不相同dex中的Common类,这样就防止了类被打上CLASS_ISPREVERIFIED的标志了,只要没被打上这个标志的类都可以进行打补丁操作。

优点:

  • 开发透明,简单;
  • 热修复成功率高。

缺点:

  • 在Art 上表现为补丁包较大;
  • 在Dalvik 上性能消耗较大。
Robust实现原理:

Robust 插件对每个产品代码的每个函数都在编译打包阶段自动的插入了一段代码。通过判断 if(changeQuickRedirect != null) 来确定是否进行热修复,当 changeQuickRedirect 不为 null 时,调用 patch.dex 中同名类的同名方法达到 hotfix 的目的。

如何调用呢?
生成的patch.dex 中有两个主要类,PatchesInfoImpl.java 和修复后的同名类 APatch.java。客户端拿到patch.dex 后,用DexClassLoader 加载patch.dex,反射拿到PatchesInfoImpl.java 这个 class。并创建这个class 的一个对象。然后通过这个对象知道被替换的是谁,给它的变量changeQuickRedirect 赋值为 patch.dex 中的 APatch 的对象,这样就会去执行补丁包中的方法了。

大致流程图如下所示:A_old 表示未被修复的原有类,A_new 表示已修复的新类。

Robust 原理流程图

优点

  • 兼容性高,开发透明;
  • 实时生效。

缺点

  • 会增大方法数,影响运行效率;
  • 暂不支持 so 文件和资源的替换。
Andfix 实现原理:

Andfix 采用的方法是,在已经加载了的类中直接在 native 层替换掉原有方法,是在原来类的基础上进行修改的。其核心在于 replaceMethod 函数,所以只支持方法替换,对于方法的增删,资源更新,so 文件更新及类和属性的替换等都是不支持的。

Andfix 的实现偏 native 层,笔者能力有限,其具体实现过程,就不妄加总结了。
更多实现细节请看 Andfix 官网文章

优点

  • 立即生效,消耗低;
  • 补丁包较小。

缺点

  • 仅支持方法替换;
  • 兼容性不佳,对部分机型暂不支持。
Tinker 实现原理:

在 App 运行到一半的时候,所有需要发生变更的 Class 已经被加载过了,在Android 上是无法对一个 Class 进行卸载的。而 Tinker 的方案,都是让 Classloader 去加载新的类。如果不重启,原来的类还在虚拟机中,就无法加载新类。因此,只有在下次重启的时候,在还没走到业务逻辑之前抢先加载补丁中的新类,这样后续访问这个类时,就会 Resolve 为新的类。从而达到热修复的目的。

Tinker 的实现过程更像是在 Qzone 热修复方案上做优化。核心点是性能最优,消耗最低。

经 Tinker 开发人员调研,Qzone 的方案最大挑战在于性能,即Dalvik平台存在插桩导致的性能损耗,Art平台由于地址偏移问题导致补丁包可能过大的问题。为了避免这两个问题,根据 Instant Run 的全量替换新的 Dex 的思路,于是决定将新旧两个Dex 的差异放到补丁包中。

经过调研,BsDiff 算法对 Dex 支持效果不太好,所以,Tinker 开发团队人员自研了 DexDiff 算法。

最终, BsDiff 加载 so 和部分资源文件,DexDiff 加载 Dex文件,以达到性能最优。但是这个方案也有缺点,就是占用 ROM 较大。好吧!现在手机内存都不小,多几十 M 可以接受。

优点

  • 补丁包较小,消耗较小;
  • 开发透明,文档丰富。

缺点

  • 占用 ROM 较大;
  • 需要重启才能生效。
数据对比:
Type Nuwa Robust Andfix Tinker
Company Null Meituan Alibaba Tencent
开发时间 2015 2016 2015 2016
替换类 X X
替换So X X X
替换资源 X X
即时生效 X X
成功率 较高 最高 一般 较高
接口文档 ★★ ★★ ★★ ★★★★

写在后头

单就热修复线上 APP 某一处或多处 bug 来说,Andfix能做到即时修复,且操作简单,不用生成较多的 patch.dex 包,能轻松解决紧急问题。

但对于如非紧急 bug 的修复及小版本的发布,对即时生效性要求不高的情况,Tinker 支持的替换内容较丰富,更胜一筹。

阿里将 Andfix 升级为商业版 SDK Sophix;腾讯将 Tinker 升级为 Bugly。
Sophix 不但支持即时修复,还支持再次启动修复类、so 文件、资源等。作为商用 APP 集成 Sophix 是很好的选择。
但 Tinker 的开源,为其带来了大量的使用者和测试者,除此以外还与各大手机厂商建立联系,使得各厂商在系统定制时也会考虑是否影响热修复的问题。所以 Tinker 的兼容性可见一斑。

总的来说,各有千秋,各需所需吧。
我们这里以 Tinker 为学习对象,接下来先让 Tinker-Demo 跑起来,看一下实际效果。
Android 热修复 - Tinker 实现及踩过的坑

记录在此,仅为学习!
感谢您的阅读!欢迎指正!
欢迎加入 Android 技术交流群,群号:155495090

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267