写在开头

从15年开始各技术大佬们开始研究热修复技术,并陆续开源了许多的热修复框架。如 Jasonross 的 Nuwa,美团的 Robust,阿里的 Andfix,腾讯的 Tinker 等等...均是Android 前辈们夜以继日的成果。而现在热修复被广泛地应用于Android 应用和游戏,运用并理解热修复框架在面试中也是加分项。所以,赶紧学起来吧...

本文以Tinker 作为学习对象,主要讲述各开源框架的对比和记录Tinker 的Demo 集成过程。

热修复框架原理总结

这一节篇幅较长,主要是用自己的话来总结各热修复框架的实现原理。如果想看Tinker接入实现的同学可进入下一章节。Android 热修复 - Tinker 实现及踩过的坑

Nuwa 实现原理:

最早看到热修复框架的相关文章就是Qzone官方的文章,但是Qzone热修复技术的实现代码并没有开源。不过GitHub上有一开源的热修复框架Nuwa,实现原理和其相似。这里我们以Qzone为例进行分析。

Qzone的实现原理是生成差分dex文件,将patch.dex插到dexElements的最前面。但patch.dex中的类patchA.java会引用classes.dex中的类classesB.java,如果这两个类所在的patch.dex和classes.dex不是同一个文件就会报错。

疑惑的Qzone技术大佬发现classes.dex和classes2.dex也不是同一个文件,为啥不报错?于是继续查,发现了这个判断

if(!fromUnverifiedConstant && IS_CLASS_FLAG_SET(referrer, CLASS_ISPREVERIFIED)){

如果被引用者(也就是classesB.java)这个类被打上了CLASS_ISPREVERIFIED标志,那么就会进行dex的校验。校验不过就报错了。

那么这个标志是什么时候被打上去的?

在apk安装的时候,虚拟机会将dex优化成odex后才拿去执行。在这个过程中会对所有class进行校验。

怎么校验的?

假设classesB.java类在它的static方法,private方法,构造函数,override方法中直接引用到classesC.java类。如果classesB.java类和classesC.java类在同一个dex中,那么classesB.java类就会被打上CLASS_ISPREVERIFIED标记,被打上这个标记的类不能被其他dex中的类引用,否则就会报错。所以要防止类被打上CLASS_ISPREVERIFIED的标志。

如何防止类被打上CLASS_ISPREVERIFIED的标志?

Common类会被打包成单独的hack.dex,这样当安装apk的时候,classes.dex内的类都会引用一个在不相同dex中的Common类,这样就防止了类被打上CLASS_ISPREVERIFIED的标志了,只要没被打上这个标志的类都可以进行打补丁操作。

优点:

开发透明,简单;

热修复成功率高。

缺点:

在Art 上表现为补丁包较大;

在Dalvik 上性能消耗较大。

Robust实现原理:

Robust 插件对每个产品代码的每个函数都在编译打包阶段自动的插入了一段代码。通过判断 if(changeQuickRedirect != null) 来确定是否进行热修复,当 changeQuickRedirect 不为 null 时,调用 patch.dex 中同名类的同名方法达到 hotfix 的目的。

如何调用呢?

生成的patch.dex 中有两个主要类,PatchesInfoImpl.java 和修复后的同名类 APatch.java。客户端拿到patch.dex 后,用DexClassLoader 加载patch.dex,反射拿到PatchesInfoImpl.java 这个 class。并创建这个class 的一个对象。然后通过这个对象知道被替换的是谁,给它的变量changeQuickRedirect 赋值为 patch.dex 中的 APatch 的对象,这样就会去执行补丁包中的方法了。

大致流程图如下所示:A_old 表示未被修复的原有类,A_new 表示已修复的新类。

Robust 原理流程图

优点

兼容性高,开发透明;

实时生效。

缺点

会增大方法数,影响运行效率;

暂不支持 so 文件和资源的替换。

Andfix 实现原理:

Andfix 采用的方法是,在已经加载了的类中直接在 native 层替换掉原有方法,是在原来类的基础上进行修改的。其核心在于 replaceMethod 函数,所以只支持方法替换,对于方法的增删,资源更新,so 文件更新及类和属性的替换等都是不支持的。

Andfix 的实现偏 native 层,笔者能力有限,其具体实现过程,就不妄加总结了。

更多实现细节请看 Andfix 官网文章

优点

立即生效,消耗低;

补丁包较小。

缺点

仅支持方法替换;

兼容性不佳,对部分机型暂不支持。

Tinker 实现原理:

在 App 运行到一半的时候,所有需要发生变更的 Class 已经被加载过了,在Android 上是无法对一个 Class 进行卸载的。而 Tinker 的方案,都是让 Classloader 去加载新的类。如果不重启,原来的类还在虚拟机中,就无法加载新类。因此,只有在下次重启的时候,在还没走到业务逻辑之前抢先加载补丁中的新类,这样后续访问这个类时,就会 Resolve 为新的类。从而达到热修复的目的。

Tinker 的实现过程更像是在 Qzone 热修复方案上做优化。核心点是性能最优,消耗最低。

经 Tinker 开发人员调研,Qzone 的方案最大挑战在于性能,即Dalvik平台存在插桩导致的性能损耗,Art平台由于地址偏移问题导致补丁包可能过大的问题。为了避免这两个问题,根据 Instant Run 的全量替换新的 Dex 的思路,于是决定将新旧两个Dex 的差异放到补丁包中。

经过调研,BsDiff 算法对 Dex 支持效果不太好,所以,Tinker 开发团队人员自研了 DexDiff 算法。

最终, BsDiff 加载 so 和部分资源文件,DexDiff 加载 Dex文件,以达到性能最优。但是这个方案也有缺点,就是占用 ROM 较大。好吧!现在手机内存都不小,多几十 M 可以接受。

优点

补丁包较小,消耗较小;

开发透明,文档丰富。

缺点

占用 ROM 较大;

需要重启才能生效。

数据对比:

Type

Nuwa

Robust

Andfix

Tinker

Company

Null

Meituan

Alibaba

Tencent

开发时间

2015

2016

2015

2016

替换类

X

X

替换So

X

X

X

替换资源

X

X

即时生效

X

X

成功率

较高

最高

一般

较高

接口文档

★★

★★

★★

★★★★

写在后头

单就热修复线上 APP 某一处或多处 bug 来说,Andfix能做到即时修复,且操作简单,不用生成较多的 patch.dex 包,能轻松解决紧急问题。

但对于如非紧急 bug 的修复及小版本的发布,对即时生效性要求不高的情况,Tinker 支持的替换内容较丰富,更胜一筹。

阿里将 Andfix 升级为商业版 SDK Sophix;腾讯将 Tinker 升级为 Bugly。

Sophix 不但支持即时修复,还支持再次启动修复类、so 文件、资源等。作为商用 APP 集成 Sophix 是很好的选择。

但 Tinker 的开源,为其带来了大量的使用者和测试者,除此以外还与各大手机厂商建立联系,使得各厂商在系统定制时也会考虑是否影响热修复的问题。所以 Tinker 的兼容性可见一斑。

总的来说,各有千秋,各需所需吧。

我们这里以 Tinker 为学习对象,接下来先让 Tinker-Demo 跑起来,看一下实际效果。

Android 热修复 - Tinker 实现及踩过的坑

android热修复原理底层替换,Android 热修复 - 各框架原理学习及对比相关推荐

  1. android r.java 原理,深入理解Android消息处理系统原理

    Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制.实际上谷歌参考了Windows的消息循环机制,也在Android系统中实现了消息循环机制. Android通过Looper.Ha ...

  2. Android加速度传感器原理,一种Android加速度传感器应用的通用解决方案

    A General Solution to Acceleration Sensor Application Based on Android Platform Liu Ying 1 刘颖,(1988- ...

  3. android大字体原理,如何让Android TextView(包括子类)的字体大...

    在使用TextView的时候,很多情况下内容的长度是要变化的,字数多了,可能不能显示全部的内容,那如何让TextView在字数超了的时候,能自动缩小字体,或者直接匹配最优的字体大小,使内容全屏并全部显 ...

  4. android中okhttp原理详解,Android中okhttp原理详解-极度针对面试篇

    一.okhttp工做的大体流程 1.一.总体流程 (1).当咱们经过OkhttpClient创立一个Call,并发起同步或者异步请求时: (2).okhttp会经过Dispatcher对咱们全部的Re ...

  5. mysql 优化 修复原理_mysql下表的修复与优化

    在很多的linux生产服务器里很多时候用数据库是mysql,在数据库里算是轻量级的数据库,但是长期以来的使用往往会出现一些问题,一般的状况是无法读取表,此时我们就要来修复表.优化表,减小磁盘使用量,以 ...

  6. Android Andfix热修复原理

    正常开发流程 热修复开发流程 当线上的项目出现问题了,需要重新发布版本解决bug,重新发新版本apk; 但是随着技术不断的更新,线上项目出现bug,可以通过热修复,在不需要发布新版本的情况下进行bug ...

  7. android studio证件照代码,Android 修图(换证件照背景,污点修复)

    背景 前段时间的一个周末,一个女生让我帮她换一下他的证件照背景,我又没带电脑.我又不好意思拒接,怎么办呢?应用商店下载一个证件照换背景的APP,瞬间换完,我正准备保存时,跳出来一个支付框,如果你要保存 ...

  8. Android 修图(换证件照背景,污点修复)

    背景 前段时间的一个周末,一个女生让我帮她换一下他的证件照背景,我又没带电脑.我又不好意思拒接,怎么办呢?应用商店下载一个证件照换背景的APP,瞬间换完,我正准备保存时,跳出来一个支付框,如果你要保存 ...

  9. Android 广播实现原理解析

    Android 广播实现原理解析 前言 Android四大组件中的BroadcastReceiver,在我们实际工作中被频繁的使用,我们可以利用系统的开机广播,网络状态改变的广播等等实现我们的业务逻辑 ...

最新文章

  1. python记录当前系统时间 生成照片直接命名
  2. Android APP开发
  3. PhotoFiltre Studio X中文版
  4. Nginx环境下PHP flush失效的解决方法
  5. sql server insert 锁表_SQL简单优化
  6. xml教程之约束schema
  7. ZT 为什么Java中继承多数是有害的?
  8. Android中attrs.xml文件的使用详解
  9. xcode编译报错unknown error -1=ffffffffffffffff Command /bin/sh failed with exit code 1
  10. java 蓝桥杯算法训练 猴子分苹果(题解)
  11. 计算机中那些事儿(九):资料管理一些建议---理论篇
  12. Android下图片处理的的一些方法
  13. 中芯国际2020年第三季度收入76.38亿元,同比增长31.7%
  14. python输入名字配对情侣网名_输入名字配置情侣网名-网名搜索
  15. Linux学习16-磁盘分区MSDOS与GPT的区别
  16. 小米网卡驱动linux,小米笔记本 Air 13.3 在 Linux Mint 下安装 nvidia 驱动
  17. SQL简体繁体转换函数代码
  18. 肝脏、心脏、脾脏、肺脏、肾脏的毒素表现以及食疗排毒
  19. 抖音短视频数据抓取实战系列(〇)——前言
  20. React中input输入框中文输入的问题

热门文章

  1. leetcode 208. Implement Trie (Prefix Tree) | 208. 实现 Trie 前缀树(Java)
  2. kubernetes入门到精通(二):k8s部署Tomcat集群,基于NTFS协议的文件集群共享,Service提供负载均衡,端口转发工具Rinetd配置外部访问
  3. MySQL调优(八):查缺补漏(mysql的锁机制,读写分离,执行计划详解,主从复制原理)
  4. 【JavaWeb】Response请求转发与重定向辨析
  5. 在gradle中构建java项目
  6. 深入理解h2和r2dbc-h2
  7. python数据科学实践指南_《Python数据科学实践指南》——导读-阿里云开发者社区...
  8. 开运算和闭运算_OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)...
  9. 循环首次适应算法_面向6G的极化编码链路自适应技术
  10. Copy-On-Write读写分离策略和CopyOnWriteArrayList源码分析