全面了解Android热修复技术
WeTest 导读
本文探讨了Android热修复技术的发展脉络,现状及其未来。
热修复技术概述
热修复技术在近年来飞速发展,尤其是在InstantRun方案推出之后,各种热修复技术竞相涌现。国内大部分成熟的主流APP都拥有自己的热修复技术,像手淘、支付宝、QQ、饿了么、美团等等。
目前能搜集到的资料,大多简单罗列每个方案的特点并进行横向比较,而其中技术发展的脉络往往被掩盖了。热修复技术从何而来,又将往何处去?在这些资料中都找不到答案。
我认为,走马观花地看一遍各家的热修复方案并不能找到答案,所以写下本文,希望从一个不同的角度来了解热修复技术,权当抛砖引玉,如有不足,欢迎指正。
代码热修复
代码热修复是最常见,也是热修复中最重要的部分,因为程序错误往往都是代码逻辑的错误。最初的热修复方案也仅支持代码热修复。代码热修复分两个流派,即腾讯系的类加载方案和阿里系的底层替换方案,前者需要重启应用但却能修复大部分错误,后者及时生效却只能作方法内的修改。下面详细介绍。
一、类加载方案
1、Qzone
Qzone的超级热修复方案是业界最早的热修复方案之一,原理简单而巧妙,影响深刻而久远,在此简单介绍。Android类加载的源码如下:
可以看出当有多个dex文件时,他们会组成一个有序数组,按顺序加载,而对于一个已经加载的Class是不会再次加载的,由此得出热修复方案:把需要修复的类打包成一个dex文件下发,并在APP启动时通过反射,将这个dex文件放在dexElements的最前面,这样修复了的Class就会比有Bug的Class优先加载了。如下图所示:
但在实现过程中,会遇到unexpected DEX problem异常,Qzone方案为了解决这个问题采用了插桩的策略来规避这个异常。实际上,Android系统的检查和优化都是有其意义的,因此这种方法在Dalvik和Art上都会遇到问题。
● 在Dalvik虚拟机,APP在安装的时候会被执行dexopt操作,同一个dex文件内的Class会被打上CLASS_ISPREVERIFIED标志,而补丁包中的类并没有打上此标志,因此抛出异常。解决方法就是在第一次打包APK时让所有类都引用另一个dex文件中的类,这样所有的类始终不会打上CLASS_ISPREVERIFIED标志,因此补丁包可以顺利加载,但是Dalvik虚拟机在检测到一个类未打上CLASS_ISPREVERIFIED之后会再次在类加载的时候进行dexopt相关的操作,如果一次性加载很多类,速度将明显变慢。
● 在Art虚拟机,dex文件最终会编译成本地机器码,在dex2oat时fast *已经将各个类的地址写死,若补丁包中的类出现字段或者方法的修改,会出现内存地址错乱,解决办法是将这个类的父类和调用这个类的类都加入补丁包。但这样会导致补丁包急剧增大。(实际上要理解清楚这个问题需要熟悉Dalvik和Art的完整流程,并非三言两语能解释清楚)
这两个问题都可以解决,但都要付出一些代价:类加载速度或者补丁包大小。
2、Tinker
如果Qzone没有上面两个缺陷,或许就不会有Tinker了。对于微信这样一个对性能有极高要求的产品来说,Qzone的缺点会被无限放大。在参考Instant Run的冷插拔与buck的exopackage后,Tinker采用了全量替换的策略。全量替换可以避免插桩和地址写死问题,但是补丁包会很大,因此可以在新旧两个Dex的差异放在补丁包中,下发到移动端后再在本地合成完整的dex文件。
实际上,Tinker保留了Qzone最核心的东西:反射修改dexElements。无论是插入还是替换,本质都是利用了类加载的特点。由于需要下发的全量补丁包体积过大,Tinker采用了后台求diff,下发diff文件,移动端合成全量包的策略。
如果仅此而已,只要有diff/patch算法,就可以开发Tinker了。实际上,确实如此。而Tinker第二个创新之处就是采用了自研的DexDiff算法,大大优化了下发差异包的大小。
二、底层替换方案
阿里的Andfix热修复方案是底层替换方案的代表,与Qzone和Tinker的思想完全不同,Andfix通过修改一个方法的入口地址来达到修复。以Dalvik虚拟机为例,Andfix的核心代码如下:
其实就是修改了方法包括入口地址在内的每一项数据的地址,使之指向一个新的方法。在后台,使用Andfix提供的apkpatch工具,可以得到补丁文件out.apatch,这个文件记录了哪些方法需要修改,以及修改后的方法。Andfix效果:
(注意我一直在点击,下发补丁后发生了变化……)
资源修复
除了代码热修复,资源热修复也很常见。各大主流方案在资源修复的实现上大多参考了InstantRun的实现方式,因此本章节先讨论了InstantRun,再分析了基于InstantRun所实现的热修复。
一、InstantRun
InstantRun在AndroidStudio2.0.0中引入。
InstantRun包括代码修复和在资源修复,资源修复的核心代码:
其实做了两件事:
1. 通过反射替换掉原有的AssetManager
2. 找到引用了原AssetManager对象的字段并替换为新的引用。
关键是要熟悉Android相关源码,才能确定哪些字段是需要更新引用的。通过以上两步即可实现资源替换。
二、资源热修复实现
将InstantRun的monkeyPatchExistingResource方法引入我们的代码就可以实现资源热修复,效果如下:
SO库热修复
so库的修复本质是对native方法的修复和替换,和类加载方案类似,可以把补丁so库的路径插入到nativeLibraryDirectories数组的最前面,使得优先加载补丁库而不是原来的库来达到修复目的。在此不做赘述。
热修复的稳定性
一、兼容的困境
最初Qzone就需要在Dalvik平台进行插桩,Tinker同样也是分平台合成(在Dalvik平台合成全量Dex,在Art平台合成需要的小Dex),而阿里的Andfix作为底层热修复方案,不仅要面对两种虚拟机平台,甚至要为不同Android版本编写一套替换逻辑,如下:
二、不安全的代码
加载了补丁包的程序本质还是未编译的程序,只是两个已编译程序的结合体,由于Java的编译过程对于我们是透明,所以我们一不小心就会引入错误,而且这种错误十分隐蔽。在使用类加载方案时由于还是在Java层,可能不那么容易犯错,但使用Andfix等底层热修复方案时却总是防不胜防。
比如,Java在编译匿名内部类时会编译成顶级类,命名方式为ClassNamen,其中n为匿名内部类出现的顺序,所以在第i个匿名内部类前面添加匿名内部类就会导致ClassNamei#methodName变成ClassName$i+1#methodName,即一个方法的地址发生改变。再比如,Java的泛型编译可能会在编译期引入新的方法,也会导致Andfix的异常。
因为编译过程是透明的,所以热修复后的程序不能代替修复问题后重新编译出来的程序,即热修复后程序的安全性是得不到保证的。
热修复技术展望
Qzone时期插桩影响了类加载的速度,Tinker的DexDiff算法粒度过细、实现复杂,导致性能消耗严重,Andfix使用场景有限、兼容性差,此外美团的Robust、饿了么的Amigo等也都各有限制。Android热修复技术虽然百花齐放,但却并没有哪种方案能够解决所有问题,统一当前的局面。而最近阿里又推出了Sophix,针对各种类型的修复又做了深度的优化,虽然没有开源代码,但是发布了《深入探索Android热修复技术原理》,引起Android社区的关注,其统一各种热修复方案的意图也十分明显。
从Qzone到Tinker,从Andfix到Sophix都可以看出来,热修复技术还在不断上升发展,每一次新方案的推出都是对原有方案的超越。但目前来看,阿里并未打算开源Sophix,而Tinker2.0仍然在路上,热修复技术在性能、兼容、开发透明方面仍然有很多不足,所以不能仅仅满足于了解已有方案,还要深入源码去理解原理,更要对业界最新进展保持关注。
参考:
1、安卓App热补丁动态修复技术介绍
2、微信Tinker的一切都在这里,包括源码(一)
3、alibaba/AndFix: AndFix is a library that offer hot-fix for Android App.
4、Instant Run: How
5、微信Android热补丁实践演进之路
6、Tencent/tinker: Tinker is a hot-fix solution library for Android, it ……
腾讯WeTest兼容性测试团队积累了10年的手游测试经验,旨在通过制定针对性的测试方案,精准选取目标机型,执行专业、完整的测试用例,来提前发现游戏版本的兼容性问题,针对性地做出修正和优化,来保障手游产品的质量。目前该团队已经支持所有腾讯在研和运营的手游项目。
iPhone8/iPhoneX新机即将同步上线,欢迎进入:http://wetest.qq.com/product/expert-compatibility-testing 使用专家兼容测试服务。 WeTest兼容性测试团队期待与您交流!You Create,We Test!
如果对使用当中有任何疑问,欢迎联系腾讯WeTest企业qq:800024531
全面了解Android热修复技术的更多相关文章
- Android热修复技术原理详解(最新最全版本)
本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结 通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...
- Android热修复技术原理详解
阿里Dexposed -- native解决方案 原理: 直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能 他的思想完全来源于Xposed框架,完美诠释 ...
- 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍
1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...
- 深入探索Android热修复技术原理读书笔记 —— 代码热修复技术
在前一篇文章 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍中,对热修复技术进行了介绍,下面将详细介绍其中的代码修复技术. 1 底层热替换原理 在各种 Android 热修复方案中 ...
- 深入探索Android热修复技术原理读书笔记 —— 资源热修复技术
该系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 1 普遍的实现方式 Android资源的热修复,就 ...
- 深入探索Android热修复技术原理读书笔记 —— so库热修复技术
热修复系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 深入探索Android热修复技术原理读书笔记 ...
- Android 热修复技术(1)---原理
热修复技术分为几部分: 原理介绍 Android HotFix源码分析 自定义框架 1.Android分包MultiDex原理 首先Dex是什么东西? Dex就是Window里面的exe文件 也就是可 ...
- Android热修复技术选型(不在市场发布新版本的情况下,直接更新app)
2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们在原理各有不同,适用场景各异,到 ...
- Android热修复技术选型——三大流派解析
声明,本文转载自微信公众号文章 2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们 ...
随机推荐
- Educational Codeforces Round 27 补题
题目链接:http://codeforces.com/contest/845 A. Chess Tourney 水题,排序之后判断第n个元素和n+1个元素是不是想等就可以了. #include < ...
- redux源码解读
react在做大型项目的时候,前端的数据一般会越来越复杂,状态的变化难以跟踪.无法预测,而redux可以很好的结合react使用,保证数据的单向流动,可以很好的管理整个项目的状态,但是具体来说,下面是 ...
- Sublime Text3 最常用快捷键
软件快捷键再多,平时常用的也就那么几个,先总结如下: 全选:Ctrl+A 复制:Ctrl+C 粘贴:Ctrl+V 删除:Ctrl+X 快速复制到下一行:Ctrl+Shift+D 快速向上移动代码:Ct ...
- java private修饰的类和变量
private主要用来修饰变量和方法,一般不会用来修饰类,除非是内部类. 1.new对象 被private修饰的变量和方法,只能在自己对象内部使用,其他对象即使是new你这个对象也是获取不到被priv ...
- CSS布局技巧大全
参考资料: http://www.imooc.com/article/2235 单列布局 水平居中 父元素text-align:center;子元素:inline-block; 优点:兼容性好: 不足 ...
- Java起源
Java历史发展和特点 作为一名合格的程序员,如果不了解一些关于Java语言的起源是有一些不太合适的.下面就介绍一下我所了解的Java起源. 1.Java名字的来源 Java是印度尼西亚爪哇岛的英文名 ...
- Net分布式系统之七:日志采集系统(1)
日志对大型应用系统或者平台尤其重要,系统日志采集.分析是系统运维.维护及用户分析的基础. 一.系统日志分类 一般系统日志可分为三大类: 1.用户行为日志:通过采集系统用户使用系统过程中,一系列的操作日 ...
- 【转】Spring AOP 实现之CGLIB
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp91 cglib(Code Generation Library)是 ...
- Linux-chown命令(1)
chown [chang owner]:更改文件的属主,也就是指定文件的拥有者改为另一个指定的用户或组. 命令格式: chown [选项]... [用户][:[组]] 文件... 例子: sudo ...
- 团队作业8——第二次项目冲刺(Beta版本)5.24
1.当天站立式会议照片 会议内容 1.总结前几次会议中出现的问题. 2.对第二天需要做的任务进行分配. 3.询问团队队员任务完成情况以及时间分配是否充分. 4.对今后的任务,发表自己的看法. 2.每个 ...