Android热修复技术选型

目前Android业内,热修复技术百花齐放,各大厂都推出了自己的热修复方案,使用的技术方案也各有所异,当然各个方案也都存在各自的局限性。在面对众多的方案,希望通过梳理这些热修复方案的对比及实现原理,掌握热修复技术的本质,同时也对项目接入做好准备。

什么是热修复技术?

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

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

怎么选择热修复技术方案?

国内主流的技术方案

缺点

接入复杂

目前最快捷的集成方式是 集成 bugly 升级sdk。

需要的工作

代理 Application

接入 tinker-support 插件

编写tinker gradle 脚本

打包复杂

每次打包需要修改tinker gradle 脚本的配置

补丁激活成功率低

测试下来发现激活成功率 大概 60%

补丁合成dex性能消耗大

主流配置的机器,平均合成时间 1800秒

价格

基础版 免费:最大补丁大小:500k 日请求量 <1万

专业版 399 - 2899元/月

Sophix

优点

补丁即时生效,不需要应用重启;

补丁包同样采用差量技术,生成的PATCH体积小;

对应用无侵入,几乎无性能损耗;

两行代码,傻瓜式接入。

价格

免费阈值:月活设备(MAU): 5万。

每个月,每台设备收费0.015元。

计费周期:系统每日生成账单,进行结算。当月收取过的,不再进行收费。即只计算日增量设备

Robust

java hook 插桩

优点

无差别兼容Android2.3-8.0版本;

无需重启补丁实时生效,

补丁修补成功率高达99.9%(所有热修复方案中成功率最高的)

缺点

只支持方法级别的Bug修复,不支持资源及so

bug修复通过java hook 代码实现

补丁的下发和合并等需要自己实现

总结



如果考虑付费,推荐选择阿里的Sophix,Sophix是综合优化的产物,功能完善、开发简单透明、提供分发及监控管理。

如果不考虑付费,只需支持方法级别的Bug修复,不支持资源及so,推荐使用Robust。补丁修补成功率高达99.9%(所有热修复方案中成功率最高的)

如果考虑需要同时支持资源及so,使用Tinker。不建议使用,因为实现原理是 dex合成后替换,dex合成成功率不高(60%)

如果公司综合实力强,可考虑自研,灵活性及可控制最强。

从Github上的热度及提交记录上看,nuwa、AndFix、Amigo等的提交都是2 years ago。

内业主要热修复技术方案原理

代码热修复方案的两个方向

底层替换和类加载(dex插入/替换)

类加载有两种实现:dexElements和替换dex;所以又称三大流派

美团 Robust 这种 java方法插桩hook的,只能实现代码修复,无法实现资源和so修复;所以不在常规讨论范围内。

底层替换方案

代表:阿里系的 Andfix HotFix

原理

通过Andfix提供的工具对比出新旧apk 的 classes.dex 文件的差异,并生成patch压缩包(jar包)

压缩包中比较关键的是 PATCH.MF (补丁类名)和 diff.dex (补丁方法)

虚拟机通过 jar包 读取 补丁类名和补丁方法

通过classLoader,找到要修复的bug类名及方法

利用hook技术,在native修改指ArtMethod针变量,使其指向补丁方法,从而完成bug修复。

优点

在类加载后,动态修改native指针,修复即时生效,无需冷启动

缺点

类已经被加载,内存中方法描述符(结构体)已经固定,所以只能替换,不能做新增修复

在Native操作指针时,强转ArtMethod的类型是AndFix写死的,无法保证是运行时的ArtMethod结构,这会产生十分严重的兼容问题

实践发现Andfix 修复成功率非常低 ,时常出现崩溃,补丁无效的现象

类加载方案

代表:腾讯系的 Qzone超级补丁(dex插入) Tinker(dex替换)

dex插入

增量Dex

原理

Hook ClassLoader.pathList.dexElements[]

将补丁的dex插入到数组的最前端。

ClassLoader的findClass是通过遍历dexElements[]中的dex来寻找类的。所以会优先查找到修复的类。从而达到修复的效果。

VM规则判断

Vm的判定规则:“当一个类中引用了另外一个类,则一般要求两个类来自同一个Dex文件”。

CLASS_ISPREVERIFIED 是触发Vm判定规则的前提。

增量方案为解决这个问题,需要进行“打桩”。

打桩的目的就是防止类被打上 CLASS_ISPREVERIFIED 标签。

打桩,就是在所有类中分别引用另外一个独立Dex文件(为了打桩特意封装的)中的类。通常做法是在每一个类中增加构造器并引用另外一个dex中的类。

在类加载的最后阶段,虚拟机会对未打上 CLASS_ISPREVERIFIED 标签的类 再次进行 校验和优化 ,如果在同一时间点加载大量类,那么就会出现严重的性能问题,如启动时白屏。

优点

不需要考虑对dalvik虚拟机和art虚拟机做适配

代码是非侵入式的,对apk体积影响不大

缺点

需要下次启动才修复

性能损耗大,为了避免类被加上 CLASS_ISPREVERIFIED,使用插桩,单独放一个帮助类在独立的dex中让其他类调用。可能导致严重的性能问题,如启动时白屏。

dex替换

全量Dex替换

原理

为了避免dex插桩带来的性能损耗,dex替换采取另外的方式(整体替换dex)。

提供dex差量包(只包含patch代码的dex)

将patch.dex与应用的classes.dex合并成一个完整的dex

加载完整dex得到dexFile对象作为参数构建一个Element对象

整体替换掉旧的dex-Elements数组

优点

相比 dex插入,dex替换的优点

减少了dex插桩带来的性能损耗

缺点

Dex合并内存消耗在虚拟机堆内存(vm heap)上,容易OOM,最后导致合并失败

两种方案总结

底层替换存在不同定制Rom的兼容性问题,同时不能做新增field的修复,但修复立即生效

类加载方案在合成全量补丁的时候存在性能问题,修复需要重启应用(冷启动),但是兼容性较好

Sophix 代码热修复-双剑合璧

Sophix对类文件修复 采用底层替换方案为主,类加载方案为次(兜底策略)的模式,将二者结合起来,并对二者另辟蹊径,加以突破。

基于底层替换方案的突破

底层替换方案通过在运行时利用hook操作native指针实现“热”的特性。但这里有一个关键点,底层替换所操作的指针,实际上是 ArtMethod 。

在类被加载,类中的每个方法都会有对应的ArtMethod,它记录了方法包括所属类和内存地址信息

Andfix正是通过篡改ArtMethod,将补丁方法ArtMethod的成员值逐一赋给旧方法,实现替换。

问题就出现在 逐一替换 上。因为Andfix的 ArtMethod 方法结构是根据Android开源代码写死的,面对国内厂商的定制,经常会导致两者ArtMethod方法结构不一致,这也是兼容问题产生的根本原因。

为了解决这个问题,Sophix采用了对旧ArtMethod进行 完整替换

通过动态测量ArtMethod的size(通过c层的mempy(dest ,src ,size)方法),进行全量拷贝。这样做无论ArtMethod被修改成什么样,只需要统一执行拷贝,就可以完成替换,完全无视修改虚拟机导致的ArtMethod结构差异。

另辟蹊径的冷启动修复

底层替换虽能使修复即时生效,但由于类加载后,方法结构已固定,这就造成使用上会有诸多限制。

相反类加载方案的使用场景更为广泛。

Sophix使用类加载作为兜底方案。在热部署无法使用的情况下,自动降级为冷部署方案。

无论是冷部署还是热部署,都需要通过同一套补丁兼顾。

Art虚拟机

在Art虚拟机下,默认支持多dex加载,虚拟机会优先加载命名为classes.dex的文件。

Sophix利用了这一点,将补丁文件命名为classes.dex,并对原有dex文件进行排序。这样一来,art虚拟机就会先加载补丁文件,后续加载的同类名的类会被忽略,最后将加载得到的dexFile把dexElements整体替换。

Dalvik虚拟机

Dalvik默认只加载classes.dex,其他dex则被忽略。

Sophix就需要一个全量dex。

tinker采用自主研发的dexDiff技术,从方法和指令的维度进行dex合成,但Dex合成过程发生在虚拟机堆内存上,修复的成功率极大的受到性能问题的影响。

为了解决这个问题,Sophix换了一种思路,从类的维度,对照补丁包中出现的类,在原有包中做删除操作。为了避免删除整个类信息而导致dex结构发生偏移,所以只对旧包中类的入口进行删除,实际上类的信息还在dex包中。这样一来,冷启动后,原有的类就不会被加载,相比Tinker的合成方案,Sophix的思路更为轻量化

总结

至此,Sophix对类文件修复的基本原理描述完毕。

可以说Sophix吸取了百家之长,对问题的解决之法堪称巧妙,展现出底层技术的重要性,若没有对虚拟机等底层技术的深耕探索,在系统框架的纷繁规则面前,也只能至于庭前止步。

参考&扩展

Android热修复技术,你会怎么选?

两种热修复方案及Sophix原理

Android热修复技术选型——三大流派解析

为什么使用 Tinker?

Sophix产品优势

Tinker 价格

Sophix 价格

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