开源库android 疑难问题

Android热修复技术选型

2020-09-21  本文已影响0人  阿里小鸟

目前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 价格

上一篇 下一篇

猜你喜欢

热点阅读