在了解补丁技术可以与适合做什么之后,我们回到技术本身。由于 Dexposed 无法支持全平台,并不适合应用到商业产品中。所以这里我们只简单介绍Andfix、QZone、微信几套方案的实现,以及它们方案面临着的问题,大家也可以参考资料中的 各大热补丁方案分析和比较 一文。

一. AndFix

AndFix 采用native hook的方式,这套方案直接使用dalvik_replaceMethod替换class中方法的实现。由于它并没有整体替换class, 而field在class中的相对地址在class加载时已确定,所以AndFix无法支持新增或者删除filed的情况(通过替换init与clinit只可以修改field的数值)。

也正因如此,Andfix可以支持的补丁场景相对有限,仅仅可以使用它来修复特定问题。结合之前的发布流程,我们更希望补丁对开发者是不感知的,即他不需要清楚这个修改是对补丁版本还是正式发布版本(事实上我们也是使用git分支管理+cherry-pick方式)。另一方面,使用native替换将会面临比较复杂的兼容性问题。

相比其他方案,AndFix的最大优点在于立即生效。事实上,AndFix的实现与 Instant Run的热插拔有点类似,但是由于使用场景的限制,微信在最初期已排除使用这一方案。

二. QZone

QZone方案并没有开源,但在github上的 Nuwa 采用了相同的方式。这个方案使用classloader的方式,能实现更加友好的类替换。而且这与我们加载Multidex的做法相似,能基本保证稳定性与兼容性。具体原理在这里不再细说,大家可以 参考这篇文章 。

本方案为了解决unexpected DEX problem异常而采用插桩的方式,从而规避问题的出现。事实上,Android系统的这些检查规则是非常有意义的,这会导致QZone方案在Dalvik与Art都会产生一些问题。

  • Dalvik; 在dexopt过程,若class verify通过会写入pre-verify标志,在经过optimize之后再写入odex文件。这里的optimize主要包括inline以及quick指令优化等。

若采用插桩导致所有类都非preverify,这导致verify与optimize操作会在加载类时触发。这会有一定的性能损耗,微信分别采用插桩与不插桩两种方式做过两种测试,一是连续加载700个50行左右的类,一是统计微信整个启动完成的耗时。

平均每个类verify+optimize(跟类的大小有关系)的耗时并不长,而且这个耗时每个类只有一次。但由于启动时会加载大量的类,在这个情况影响还是比较大的。

  • Art; Art采用了新的方式,插桩对代码的执行效率并没有什么影响。但是若补丁中的类出现修改类变量或者方法,可能会导致出现内存地址错乱的问题。为了解决这个问题我们需要将修改了变量、方法以及接口的类的父类以及调用这个类的所有类都加入到补丁包中。这可能会带来补丁包大小的急剧增加。

这里是因为在dex2oat时fast*已经将类能确定的各个地址写死。如果运行时补丁包的地址出现改变,原始类去调用时就会出现地址错乱。这里说的可能不够详细,事实上微信当时为了查清这两个问题,也花费了一定的时间将Dalvik跟Art的流程基本搞透。若大家对这里感兴趣,后续在单独的文章详细论述。

总的来说,Qzone方案好处在于开发透明,简单,这一套方案目前的应用成功率也是最高的,但在补丁包大小与性能损耗上有一定的局限性。特别是无论我们是否真正应用补丁,都会因为插桩导致对程序运行时的性能产生影响。微信对于性能要求较高,所以我们也没有采用这套方案。

三. 微信热补丁方案

有没有那么一种方案,能做到开发透明,但是却没有QZone方案的缺陷呢?Instant Run的冷插拔与buck的 exopackage 或许能给我们灵感,它们的思想都是全量替换新的Dex。即我们完全使用了新的Dex,那样既不出现Art地址错乱的问题,在Dalvik也无须插桩。当然考虑到补丁包的体积,我们不能直接将新的Dex放在里面。但我们可以将新旧两个Dex的差异放到补丁包中,最简单我们可以采用BsDiff算法。

简单来说,在编译时通过新旧两个Dex生成差异path.dex。在运行时,将差异patch.dex重新跟原始安装包的旧Dex还原为新的Dex。这个过程可能比较耗费时间与内存,所以我们是单独放在一个后台进程:patch中。为了补丁包尽量的小,微信自研了DexDiff算法,它深度利用Dex的格式来减少差异的大小。它的粒度是Dex格式的每一项,可以充分利用原本Dex的信息,而BsDiff的粒度是文件,AndFix/QZone的粒度为class。

这块后面我希望后面用单独的文章来讲述,这里先做一个铺垫,大致的效果如下图。在最极端的情况,由于利用了原本dex的信息完全替换一个13M的Dex,我们的补丁大小也仅仅只有6.6M。

但是这套方案并非没有缺点,它带来的问题有两个:

  • 占用Rom体积;这边大约是你修改Dex数量的1.5倍(dexopt与dex压缩成jar)的大小。
  • 一个额外的合成过程;虽然我们单独放在一个进程上处理,但是合成时间的长短与内存消耗也会影响最终的成功率。

微信的热补丁方案叫做Tinker,也算缅怀一下Dota中的地精修补匠,希望能做到无限刷新。

限于篇幅,这里对Dex、library以及资源的更多技术细节并没有详细的论述,这里希望放在后面的单独文章中。我们最后从整体比较一下这几种方案:

若不care性能损耗与补丁包大小,QZone方案是最简单且成功率最高的方案(没有单独的合成过程)。相对Tinker来说,它的占用Rom体积也更小。另一方面,QZone与Tinker的成功率大约相差3%左右。

事实上,一个完整的框架应该也是一个容易使用的框架。Tinker对补丁版本管理、进程管理、安全校验等都有着很好的支持。同时我们也支持gradle与命名行两种接入方式。希望在不久的将来,它可以很快的跟大家见面。

微信的热补丁应用现状

上一章节我们简单比较了各个热补丁的技术方案,它们解决了如何生成与加载补丁包的问题。但一个完善的热补丁系统不应该仅限于此,它还需要包括以下几个方面:

  • 网络通道;这里要解决的问题是决定补丁以何种方式推送给哪部分的用户。
  • 上线与后台管理平台;这里主要包括热补丁的上线管理,历史管理以及上报分析,报警监控等;

一. 网络通道现状

网络通道负责的将补丁包交付给用户,这个包括特定用户与全量用户两种情况。事实上,微信当前针对热补丁有以下三种通道更新:

  • pull通道; 在登陆/24小时等时机,通过pull方式查询后台是否有对应的补丁包更新,这也是我们最常用的方式;
  • 指定版本的push通道; 针对版本的通道,在紧急情况下,我们可以在一个小时内向所有用户下发补丁包更新。
  • 指定特定用户的push通道;对特定用户或用户组做远程调试。

事实上,对于大部分的应用来说,假设不实现push通道,CDN+pull通道实现起来还是较为容易。

二. 上线与管理平台现状

上线与管理平台主要为了快速上线,管理历史记录,以及监控补丁的运行情况等。

事实上,微信发布热补丁是非常慎重的。它整个发布流程与升级版本是保持一致的,也必须修改版本号、经过严格的完整测试流程等。我们也会通过灰度的方式上线,同时监控补丁版本的各个指标。这里的为了完整的监控补丁的情况,我们做的工作有:

  • 1分钟粒度的每小时/每天的各版本累积用户,及时监控补丁版本的人数与活跃;
  • 3分钟粒度的Crash统计,基准版本与补丁版本的Crash每小时/每天的两个维度对照;
  • 10分钟粒度的补丁监控信息上报。

三. 补丁成功率现状

应用成功率= 补丁版本人数/补丁发布前该版本人数 由于可能存在基准或补丁版本用户安装了其他版本,所以本统计结果应略为偏低,但它能现实的反应补丁的线上覆盖情况。

使用Qzone方案,微信补丁在10天后的应用成功率大约在98.5%左右。使用Tinker大约只有95.5%左右,主要原因在于空间不足以及后台进程被杀。在这里我们也在尝试使用重试的方式以及降低合成的耗时与内存,从而提升成功率。

热补丁技术发展的很快,Android推出的Instant App也令人期待。但是在国内,似乎我们还是指望自己更靠谱一点。每一个的应用的需求都不太一致,这里大致讲了一些微信的实践经验,希望对大家有帮助。

未来工作

随着微信部门内从“单APP”向“多APP”演进,微信也正在迈入开源化的开发实践。我们希望将各个功能组件化,从而做可以到快速复制与应用。微信的热补丁框架“Tinker”当前也在经历从微信分离,又合入到微信的过程。希望在不久的将来,我们也可以将“Tinker”以及微信中一些其他的组件开源出去。

我们也希望可以找一个App作为内测,给我们提供宝贵的意见。若对微信的Tinker方案感兴趣的用户,可以单独发消息或在文章末留言。注明姓名、所在公司以及负责的App,我们希望挑选部分产品作为内测。

微信Android热补丁实践演进之路-andFix / ClassLoader / Tinker相关推荐

  1. 【腾讯bugly干货分享】微信Android热补丁实践演进之路

    为什么80%的码农都做不了架构师?>>>    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://bugly.qq.com/bbs/forum.ph ...

  2. Tinker -- 微信Android热补丁方案 接入指南

    这两年来热修复对与移动开发是比较热门的话题,  HotFix  能做什么?他可以在用户无感知的情况下,后台修复出现的 bug,不需要通过升级发版新App,对用户体验来说是很大的提升,因为频繁发版的话, ...

  3. Tinker -- 微信Android热补丁方案 常见问题

    Tinker 常见问题 Issue/提问须知 在提交issue之前,我们应该先查询是否已经有相关的issue.提交issue时,我们需要写明issue的原因,以及编译或运行过程的日志(加载进程以及Pa ...

  4. 【腾讯Bugly干货分享】微信热补丁Tinker的实践演进之路

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ad7a70eaed47bb2699e68e Dev Club 是一个交流移动 ...

  5. Android 热补丁技术——资源的热修复

    前言 今年真是热补丁框架的洪荒之力爆发的一年,短短几个月内,已经出现了好几个热修复的框架了,基本上都是大同小异,这里我就不过多的去评论这些框架.只有自己真正的去经历过,你才会发现其中的 大写的坑 事实 ...

  6. 微信Android热更新Tinker使用详解(by 星空武哥)

    转载请标注原创地址:http://blog.csdn.net/lsyz0021/article/details/54694260 Tinker是什么 Tinker是微信官方的Android热补丁解决方 ...

  7. Android热补丁之Robust(三)坑和解

    在前两篇文章中,分析了 Android 热补丁框架 Robust 中,几个重要的流程包括: 补丁加载过程 基础包插桩过程 补丁包自动化生成过程 本篇文章主要分析下集成过程中遇到的坑以及分析问题的思路和 ...

  8. Android 热补丁动态修复框架小结

    Android 热补丁动态修复框架小结 转载于:https://www.cnblogs.com/zhujiabin/p/7923233.html

  9. Android热补丁动态修复技术

    Android热补丁动态修复技术(一):从Dex分包原理到热补丁 一.参考 博文:安卓App热补丁动态修复技术介绍--by QQ空间终端开发团队  博文:Android dex分包方案--by 猫的午 ...

  10. Android 热补丁动态修复总结 eclipse版

    参考文章 1. http://blog.csdn.net/lmj623565791/article/details/49883661  鸿翔博客 2. https://mp.weixin.qq.com ...

最新文章

  1. html5游戏 虚拟主机,基于HTML5的云虚拟主机配置界面
  2. Spring Cloud云架构 - SSO单点登录之OAuth2.0登录流程(2)
  3. dubbo总结——dubbo的使用场景
  4. react单选框获取值
  5. Android之四大组件(Service的开启与关闭)
  6. Spring JDBC-Spring对DAO的支持
  7. macOS下使用anaconda相关系列
  8. 小程序完整对接 pingpp支付
  9. [Tip]什么是3D 电影 和 4D立体电影?
  10. struct and union
  11. 你连简单的枚举类都不知道,还敢说自己会Java???滚出我的公司
  12. easyUI validate函数【总结篇-部分转】
  13. srt编辑的文件在linux显示乱码,解决看本地视频srt字幕乱码问题教程-srt文件
  14. Docker使用(三)使用Dockerfile创建镜像以及为镜像添加SSH服务
  15. moodle 中文文件名无法打开和下载问题
  16. java查询mongodb数据_从mongodb中查询数据
  17. 51单片机 74LS138译码器流水灯+Proteus仿真
  18. 喜马拉雅FM下载的音频文件保存在哪_怎么导出来
  19. 解决Minimum supported Gradle version is 4.6. Current version is 2.4.0
  20. KingbaseES V8R6集群管理运维案例之---repmgr standby switchover故障

热门文章

  1. 测试所用的技术(黑盒、白盒测试等)
  2. pli测试50题题库_【马士基销售代表面试】性格测试+12分钟50道题。-看准网
  3. dubbo暴露出HTTP服务
  4. DBCP连接池配置优化分析
  5. MongoTemplate根据时间查询的大坑
  6. 实战录 | 前端性能优化二三事儿
  7. 用计算机运算符编写检索式,在计算机检索中,常用的布尔逻辑算符有哪几种
  8. 30分钟读懂Linux五大模块内核源码,内核整体架构设计
  9. mysql多表关联查询慢_mysql数据库多表关联查询的慢SQL优化
  10. 连上wifi浏览器不能上网微信却可以登陆