Android 热修复技术浅析
转载请注明本文出自 clevergump 的博客:http://blog.csdn.net/clevergump/article/details/54782635, 谢谢!
一. 热修复技术简介
什么是热修复技术?
通过向用户下发补丁包的方式, 让应用能够在无需重新安装的情况自动集成补丁包, 实现更新的技术.
二. 热修复技术的优缺点
优点:
- 无需重新发布到应用市场, 节省了从提交应用市场审核到审核通过的时间.
- 用户无需重新安装,只要上线就能无感知地更新.
缺点:
- 补丁只能针对单一客户端版本,随着版本差异变大补丁体积也会增大.
- 补丁不能支持所有的修改,例如AndroidManifest.
- 补丁无论对代码还是资源的更新成功率都无法达到100%.
结论:
热修复技术只适用于特定场景,无法完全代替传统的升级方式.
三. 热修复技术的适用场景
1. 轻量而快速的升级
适用于修改量较少, 补丁包较小的情况。在补丁包极小的情况下,也可以直接使用移动网络下载更新, 这样能达到快速升级、快速验证、缩短发布流程的目的. 注意:是否需要使用用户流量,需要慎重考虑。例如: 下图是微信某次升级试验中, 两种升级方式的对比:
2. 静默远程bug调试和验证
3. 数据统计
如果想对同一批用户做两种测试, 传统方式无法让这批用户去安装两个版本。使用热修复技术,就可以方便地对同一批用户不停地更换补丁, 然后得出不同的测试结果, 进行数据统计和对比分析. 例如: 如果想探究某次技术升级后的用户满意度或bug出现率, 就可以使用AB测试, 只给一部分用户推送升级补丁, 其他用户则依然保持原先的版本, 通过对比这两类用户各自的使用状况, 从而就可以知道这次热修复的内容是否需要继续完善或改进等. 如果发现使用了补丁包的用户的满意度提高了, 或者出现bug的概率降低了, 那么就可以将本次热修复的补丁包下发给所有用户了.
4. 其他
例如: Android Studio 的 Instant Run (热部署) 技术等.
四. 当前主流热修复方案简介及对比
1. 微信Tinker方案
开发团队 | 微信 |
---|---|
方案简介 | 使用 ClassLoader 动态加载多个dex文件,改变dex文件的加载顺序 |
优点 | 开发简单透明,成功率较高,支持Java、so、资源文件的替换和新增,补丁包较小,性能损耗较小,支持gradle。 |
缺点 | Dalvik机型Rom体积较大,补丁不能即时生效。 |
是否开源 | 是 |
技术支持情况 | 有官方技术支持QQ群 (群号: 377388954) |
GitHub主页 | https://github.com/Tencent/tinker |
2. 腾讯QZone方案
开发团队 | QQ空间 |
---|---|
方案简介 | 使用 ClassLoader 动态加载多个dex文件,改变dex文件的加载顺序. |
优点 | 开发简单透明,成功率较高,支持so、资源文件的替换 |
缺点 | 补丁包较大,性能损耗较大,补丁不能即时生效,不支持新增Java文件. |
是否开源 | 否 |
技术支持情况 | 无(因为不开源) |
类似开源方案 | Nuwa, RocooFix |
3. 阿里巴巴AndFix方案
开发团队 | 阿里巴巴 |
---|---|
方案简介 | 采用native hook,替换class中方法的实现. |
优点 | 补丁即时生效,性能损耗较小,Rom体积较小. |
缺点 | 开发复杂,native异常排查难度高,稳定性和兼容性不好,成功率不高,不支持新增Java文件,不支持so、资源文件的替换,不支持gradle. |
是否开源 | 是 |
技术支持情况 | 不确定是否有专门的技术支持团队 |
GitHub主页 | https://github.com/alibaba/AndFix |
4. 美团Robust方案
开发团队 | 美团 |
---|---|
方案简介 | 使用 ClassLoader 动态加载多个dex文件,改变dex文件的加载顺序,同时又借鉴了multidex的设计. |
优点 | 成功率最高,补丁即时生效,性能损耗较小,Rom体积较小. |
缺点 | 开发复杂不透明,不支持新增Java文件,不支持so、资源文件的替换,不支持gradle. |
是否开源 | 否 (今后有可能开源) |
技术支持情况 | 无 (因为暂未开源) |
5. 当前主流方案的对比
方案名称 | Tinker | QZone | AndFix | Robust |
---|---|---|---|---|
类替换 | yes | yes | no | no |
So替换 | yes | no | no | no |
资源替换 | yes | yes | no | no |
全平台支持 | yes | yes | yes | yes |
即时生效 | no | no | yes | yes |
性能损耗 | 较小 | 较大 | 较小 | 较小 |
补丁包大小 | 较小 | 较大 | 一般 | 一般 |
开发透明 | yes | yes | no | no |
复杂度 | 较低 | 较低 | 复杂 | 复杂 |
gradle支持 | yes | no | no | no |
Rom体积 | 较大 | 较小 | 较小 | 较小 |
成功率 | 较高 | 较高 | 一般 | 最高 |
是否开源 | 是 | 否 | 是 | 否 |
技术支持情况 | 有官方QQ群 | 无 | 无 | 无 |
五. 当前商用APP推荐使用的热修复方案
通过前边各大方案的对比可知, 微信Tinker方案相对于其他方案具有如下优势:
- 几乎支持所有文件的替换,包括:Java文件,资源文件,so文件等。
- 稳定性高。该方案已应用于微信APP中,其稳定性已得到了微信上亿用户的验证。
- 官方更新维护及时,且代码已开源,代码是在 framework层 (而不是 native层) 进行修改, 这样可以让更多从事 APP开发或 framework开发的同行参与到该方案的维护中,从而促进了该方案的快速完善。
- 有相关的技术支持QQ群,如有疑问可以直接和开发人员沟通讨论, 便于快速解决技术难题。
所以,对于商用APP,当前推荐使用微信Tinker方案。
六. 热修复技术原理分析(开源nuwa方案)
下面以开源框架 nuwa (https://github.com/jasonross/Nuwa) 为例,来介绍基于ClassLoader的相关热修复方案的实现原理。
基于ClassLoader实现热修复,简单来说,就是把多个dex文件塞入到 APP 的 ClassLoader之中. 如果多个dex文件中有重复的类,当用到这个重复的类的时候, 系统内部会按照一定的优先级顺序先后遍历各个dex文件, 只要在某个dex文件中找到了该类, 就会停止后续的遍历, 所以后续其他 dex中具有同名的类就不会被调用了.
假设一个 APP被分成多个dex文件, ClassLoader要从中找出 Bug.class文件进行加载, 而 dex文件的优先级是: classes1.dex > classes2.dex > classes3.dex > … 那么, ClassLoader 查找该 class文件的流程图如下:
所以, 如果一个类存在bug (假设该类名为 Bug.java), 那么修复步骤如下:
- 修复Bug.java 中的bug代码
- 将修复了bug后的 Bug.java 文件所编译出的class文件打包成dex文件(假设名为patch.dex)
- 将patch.dex文件注入到原APP中, 并且需要让该dex被系统的 ClassLoader遍历时的优先级最高, 这样, 原先存在bug的那个Bug.class文件就会因为优先级较低而不会被加载了.
如何让patch.dex的优先级最高呢?
简单来说, 组成一个 APP的所有 dex文件都被存放在一个叫做 dexElements 的数组中, ClassLoader 要遍历查找某个 class文件, 其实就是从 dexElements 数组中按照数组索引从0开始逐渐增大的顺序, 一个一个地取出 dex文件进行查找, 只要找到就立即结束. 数组索引越小的 dex文件, 就越会被 ClassLoader优先遍历. 所以, 要想让一个dex文件被 ClassLoader查找的优先级最高(也即: 被 ClassLoader第一个查找), 只需将该 dex文件放在该数组的索引0位置处即可. 我们可以利用发射技术, 获取到该数组, 然后将补丁文件 patch.dex注入到该数组中的索引0位置即可.
(注意: 以上只是为了便于理解而简化了的描述, 实际情况更复杂, 需要看具体的源码)
patch.dex 注入时的 CLASS_ISPREVERIFIED 问题
在按照上述步骤注入 patch.dex时, 却可能会报如下错误, 为什么?
其实, 虚拟机为了性能考虑, 加载的不是 dex文件, 而是将 dex经过进一步优化后的 odex文件. 虚拟机在生成 odex文件的过程中, 会判断某个类是否引用了其他 dex文件中的代码, 如果没有, 则会为该类打上CLASS_ISPREVERIFIED 标签, 表示此后该类将一直不会引用其他 dex文件中的代码, 这其实是一种优化.
所以, 假设我们原先的 APP中有两个类: Caller类和 Bug类, 二者都在同一个 dex文件中, 并且Caller类中会调用 Bug类的代码, 而没有调用其他 dex文件中的代码, 那么当我们安装该 APP时, Caller类就会被打上CLASS_ISPREVERIFIED 标签. 此后, 我们发现 Bug类的代码存在 bug需要修复, 如果采用热修复技术, 那么就意味着 Caller类需要调用来自 patch.dex中的 Bug类, 也就是需要调用其他 dex文件中的代码, 由于 Bug类先前已被打上 CLASS_ISPREVERIFIED 标签, 所以会报错, 热修复失败. 要想继续使用热修复技术, 就必须阻止 Caller类被打上该标签. 更广泛地说, 要想避免该问题, 就必须要让原先 APP中的所有类都不能打上该标签.
如何让APP中的所有类都不打上 CLASS_ISPREVERIFIED 标签?
其实很简单, 只需在 APP的第一个版本中就内置一个 dex文件, 让 APP中的所有类都去调用该 dex文件中的某个类即可. 这也就是业内俗称的 “插桩”技术.
例如: 可以在 APP的 assets文件夹中内置一个 hack.dex文件, 该hack.dex文件中只包含一个 Hack.class文件. 然后在该 APP的所有类中都调用如下代码:
System.out.println(Hack.class);
七. demo代码下载
- NuwaDemo: https://github.com/clevergump/NuwaDemo
八. 参考资料
1. 微信Tinker方案:
- 微信Android热补丁实践演进之路 https://github.com/WeMobileDev/article/blob/master/%E5%BE%AE%E4%BF%A1Android%E7%83%AD%E8%A1%A5%E4%B8%81%E5%AE%9E%E8%B7%B5%E6%BC%94%E8%BF%9B%E4%B9%8B%E8%B7%AF.md#rd
- tinker GitHub: https://github.com/Tencent/tinker
2. QZone方案及类似的开源框架
- QQ空间终端开发团队—安卓App热补丁动态修复技术介绍 http://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=0#wechat_redirect
- Nuwa GitHub: https://github.com/jasonross/Nuwa
- HotFix (Deprecated) GitHub: https://github.com/dodola/HotFix
- RocooFix GitHub: https://github.com/dodola/RocooFix
3. Alibaba AndFix方案
- AndFix GitHub: https://github.com/alibaba/AndFix
4. 美团Robust方案
- Android热更新方案Robusthttps://zhuanlan.zhihu.com/p/22495059#!
5. 其他
- Android 热修复,没你想的那么难 http://kymjs.com/code/2016/05/08/01
- 各大热补丁方案分析和比较
http://blog.zhaiyifan.cn/2015/11/20/HotPatchCompare/
Android 热修复技术浅析相关推荐
- 深入解析阿里Android热修复技术原理
前言:本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结 通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简 ...
- Android热修复技术原理详解(最新最全版本)
本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结 通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...
- 深入探索android热修复技术原理_打卡活动:技术书籍书单
不知不觉,码个蛋打卡活动都已经60多天了,好多小伙伴都已经可以领取第一波奖励:技术书籍了,上周好多小伙伴私信码仔,问都有哪些技术书籍,码仔今天就给大家列了个书单供大家选择: 01 Android软件安 ...
- Android热修复技术初探(三):动态加载外部资源
前面已经介绍了Android平台上的几种ClassLoader,这几种ClassLoader都有各自的使用场景,有了这些基础知识之后,才能更好地理解以及探究Android热修复技术.首先我们来探究怎么 ...
- Android热修复技术选型参考
背景 热修复就是通过下发补丁包,让已安装的客户端动态更新,用户不用重新安装APP,就能够修复软件缺陷. 热修复技术对比 1.公司角度 大致可以分为阿里系和腾讯系和其他,如下: 阿里系 Dexposed ...
- [读书笔记] 深入探索Android热修复技术原理 (手淘技术团队)
热修复技术介绍 探索之路 最开始,手淘是基于Xposed进行了改进,产生了针对Android Dalvik虚拟机运行时的Java Method Hook技术--Dexposed. 但该方案对于底层Da ...
- android热修复技术tinker,Android热修复方案第一弹——Tinker篇
背景 一款App的正常开发流程应该是这样的:新版本上线-->用户安装-->发现Bug-->紧急修复-->重新发布新版本-->提示用户安装更新,从表面上看这样的开发流程顺理 ...
- 热修复系列——Android热修复技术进阶篇
目录 1 前言 2 热修复技术 2.1 Dexposed 2.2 AndFix 2.3 QZone 2.4 Tinker 2.6 epic 2.7 YAHFA 2.8 FastHook 2.9 美团R ...
- 性能优化——Android热修复技术,类加载机制详解
一.背景 热修复技术慢慢的成为Android开发必不可少的技术,也是成为一名高级程序员必不可少的技能之一.那么什么是热修复技术呢? 当app上线之后,发现了一个严重的bug,需要紧急修复,按照以往的惯 ...
最新文章
- 通过mrtrix3进行概率纤维追踪+核磁共振影像数据处理
- 近期学习的原生JS知识以及jQuery框架
- HDU 5044 Tree 树链剖分
- HBase:为客户行为生成搜索点击事件统计信息
- 一个职场小白想当程序员,该从哪学起?做好三大准备,完全不是问题!
- IT桔子分布式项目1
- 异步执行线程的两种方法
- mysql5.7.11 linux_CentOS 7 中以命令行方式安装 MySQL 5.7.11 for Linux Generic 二进制版本教程详解...
- 用户控件中图片路径问题(用户控件、图片路径) ,ResolveUrl
- Android O后台服务限制总结
- jira 6.X或confluence5.X linux/centos/ubuntu下设置开启启动
- 二阶振荡环节的谐振频率_什么是谐振器?谐振器与振荡器有什么区别?
- POJ 1947 Rebuilding Roads
- Linux系统:基本开发工具
- java如何让坦克动起来_[笔记]基于java的坦克大战游戏实现思路
- 卫星导航定位误差之多路径地球自转相位缠绕相位中心误差地球潮汐
- 4. 查询表orders——检索所有订单订购物品的总数
- 2015中兴笔试+面试
- 衣服尺码自定义排序sql
- .NET新手系列(九)
热门文章
- 高通ARIOS源码开发之更换识别卡片以及更换模型
- 计算机科学多久能见刊,投稿到见刊时间_sci接收到见刊一般多久_论文从录用到见刊最短多长时间...
- matlab 调速系统试验,实验三 开环直流调速系统Matlab仿真
- Android——处理R文件丢失或报错问题
- 详细的easyExcel填充数据填充图片及导出示例
- 独家解读!京东高可用分布式流数据存储的架构设计
- 基于Matlab使用线性FM波形对带状合成孔径雷达系统建模(附源码)
- 工业相机背光补偿介绍
- 性能测试之cpu 分析
- 数据库系统概述-4个基本概念、 数据管理技术的产生和发展、 数据库系统的特点