全网独家盘点Android热修复方案(含阿里巴巴、美团、腾讯等)

上一个大的系列文章叫 “手把手讲解”, 历时10个月,出产博文二十余篇,讲解细致,几乎每一篇都提供了详实的原理讲解,提供了可运行 githubDemo,并且针对Demo中的关键地方进行了重点拆解。相信每一位详细阅读文章的同行都会有所收获。但是,讲解虽详细,但是缺乏对于技术的深度的挖掘。

从今天开始开辟新的专题: 移动架构师专业技能深入浅出,以一步步成为架构师为目标,详述一项架构师技能的最直接使用价值,横向周边知识以及纵深专业技术.

最直接使用价值: 网上最怕看到一种文章,全文开篇高大上,让人觉得遥不可及,通篇看下来却没有展示技术如何落地,落地之后是何种效果。文章写出来,就要以最容易让人接受的方式带读者进入作者的世界,而不是装作一副高高在上的样子俯视众生。所以,文章开篇,一定是最直接的展示技术的落地效果。提供可运行Demo可以让读者亲自尝试。

横向周边知识: 一项核心技术,必然不是独立存在,技术是一个体系,但是一篇文章能够详述的技术有限,必然是以一项技术为中心,其他技术作为辅助。核心技术需要详述,但是周边技术,也需要交代,参天大树拔地而起也少不得土壤作为依附。用简明的语言交代周边知识,并提供这些知识正确的研究方向。也是一个负责任的博文作者不可忽视的一步。

纵深专业技术: 做技术,最忌讳的就是浅尝辄止。稍微深入一点就退出去,一来不利于理解底层实现,长此以往永远只是一个技术小白,成不了大师;二来不利于长久记忆, 记忆力再强的人时间长了,技术细节必然会记忆模糊。但是如果深入内核,理解了原理,在技术的大方向上绝对不会偏差。作为要成为架构师的男人,即使记不了那么多细节,但是对于大方向的把握绝对不能错。所以,技术纵深很有必要。

前情提要

上一篇 Android Muitldex热更新修复方案原理提到了 热修复的其中一种Muitidex方案,并且给出了演示Demo。但是真正完整去展现现实中的 热修复开源框架,远远不够。

正文大纲

  • 阿里AndFix 方案

  • 美团 Robust方案

  • 腾讯 Tinker dexdiff / DexMerge方案

  • 腾讯 QZone Muitidex方案

正文

热修复方案按照是否必须重启 分为两类: 重启生效 / 即时生效。按照 实现方式可以分为3类: java层的实现 / native层的实现 / java native混合实现

阿里AndFix 方案(已弃用)

AndFix 是 无需重启 的 native层 的实现. 但是,AndFix目前已经3年多没维护更新。因为阿里已经有了新的替代方案,不再需要维护。另外,这种纯native的实现方式,兼容性十分堪忧。既然已经被弃用,但是稍微了解一下 实现方案也是没问题的。

上图解读:图中有一段程序按照 A=>B=>C的顺序去执行,然而发现执行到B的时候,存在一个bug,AndFix的修复方式为:在native层执行到B方法的时候,把方法的指针指向了 补丁包里的B方法,绕过了原来的B方法。从而达到了修复bug的目的。

使用方法:

在需要修复的方法上面,加上@MethodReplace注解,给定参数,class和method,表示 该方法替换为 哪个类的哪个方法。

缺陷:修复粒度为:method. AndFix只能以方法为粒度去修复bug。作用有限,针对大范围的类替换和资源替换,那就无能为力了。

美团 Robust方案

Robust 是 即时生效的Java层实现的热修复实现方案.

美团的Robust方案,是参考了谷歌的InstantRun方案(之前在androidStudio里面有这个选项,可以选择打开instant run运行app)的思路而设计出来的。

其主要设计思想就是一句话:编译打包时,在程序的某些方法里面,都插入一段代码(全自动操作):

当 changeQuickRedirect不为空的时候,该方法就会命中 if(changeQuickRedirect!=null),从而执行修复的实现代码。当为空的时候,则正常执行原逻辑。

而平时我们自己编码,只需要加上一个 @modify注解,来标记这个方法需要打补丁包,也就是需要插入上面这个 if(changeQuickRedirect!=null)代码段。 

为什么它可以即时生效?

上图解析:利用ClassLoader,当客户端手机收到补丁包 patch.dex的时候,执行补丁包,把指定方法的 changeQuickRedirect用反射的手段赋值,让它变成非空。从而让下一次程序逻辑走到这里的时候,走修复之后的逻辑。

Robust是如何将这么多 ****if(changeQuickRedirect!=null)代码段插入到代码逻辑中的?:

上图中的 if(changeQuickRedirect!=null)代码段,并非我们手动编写,而是由Robust框架自动插入的。这个技术叫做 字节码插桩,意为:对class进行操作,按照class文件的格式,插入自己想要的逻辑。目前Robust支持两种字节码插桩方案 AspectJ 和 Javasist.

腾讯 Tinker dexdiff / DexMerge方案

Tinker 是腾讯自研的 重启生效的 Java层的实现.

原理

Tinker基于一个基准dex,以及修复bug之后的dex,使用dexdiff算法,计算出差分包dex。然后把差分包推送给客户端,客户端收到之后,重启运行app,把差分包dex和原dex进行合并,形成新的dex。然后ClassLoader去创建类class对象的时候,就会创建修复bug之后的类class对象。从而达到 修复bug的目的。 

Dexdiff算法

了解增量更新的人应该知道 bsdiff。bsdiff是无视文件格式,生成两个二进制文件的差异文件。dexdiff是基于bsdiff,并且进行了针对dex文件格式的优化。Tinker除了支持Dex修复之外,还支持so修复,只不过so的差分包,是直接使用的bsdiff算法生成的。

腾讯 QZone Muitidex方案

Multidex方案是 基于ClassLoader的 纯java实现 的 重启生效的热修复方案.

原理

Apk打包的时候可能生成多个classes.dex文件。JVM中 类加载器ClassLoader,在程序运行使用到某一个Class的时候,是按照顺序查找的方式进行的。一旦找到,就会缓存起来,下一次loadClass就不会去查找,而是直接使用缓存中的(所以Muitldex方案必须重启app). 而,当我们把补丁dex文件放到 顺序查找的最前面,那么类加载器 查找到它之后,就会直接使用。原来的同样的类便处于后方,不会再生效。由此,使用补丁Class完全替换了 原class.

至于更深入的原理,上一篇 Android Muitldex热更新修复方案原理已经给出了详细讲解。在此就不赘述。

方案对比

题外话

随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑、快速迭代的目的越来越难,还有65535,应用之间的互相调用等等问题,插件化技术应用而生。如果没有插件化技术,美团、淘宝这些集成了大量“app”的应用,可能会有几个g那么大。

所以,当今的Android移动开发,不会热修复、插件化、组件化,80%以上的面试都过不了。

本人从网上搜集到了阿里P8大佬花了将近半个月时间将Android热修复框架、插件化框架、组件化框架、图片加载框架、网络访问框架、RxJava响应式编程框架、IOC依赖注入框架、最近架构组件Jetpack等等Android第三方开源框架整合成了一套系统知识笔记PDF,长达1042页!相信看完这份文档,你将会对这些Android第三方框架有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容,1042详细完整版的【Android设计思想解读开源框架】文档领取方式:点赞+关注,然后私信关键词 【1】即可获得免费领取方式!

posted @ 2020-11-30 08:44  AndroidAlvin  阅读(1190)  评论(0编辑  收藏  举报