目前Android热修复的技术方案大致可以归类为以下几种:

  • 代码热修复
  • 资源热替换
  • 动态库替换​​​​​​​

代码热修复

代码热修复方案可以归纳为以下3种:类加载方案、底层替换方案、Instant Run方案

1、类加载方案

基于DexPathList.java的findClass方法处理逻辑再利用类加载机制的双亲委托模型来实现Bug

类的动态修复

2、底层替换方案

与类加载方案不同的是,底层替换方案不会再次加载新类,而是直接在Native层修改原有的类,使其功能立即生效。

拿方法替换来说,我们的方法在ART虚拟机中都对应着一个ArtMethod结构体

3、Instant Run方案

这个也是借鉴了Instant Run里的ASM动态注入技术。什么是ASM?ASM是一个Java字节码操控框架,它能够动态的生成类或者增强类的实现。ASM可以直接生成class文件,也可以在类被加载到虚拟机之前动态的改变类的行为。

资源修复

  • 合并插件资源方案: 将插件资源合并加载到宿主中
  • 独立插件资源方案: 创建插件新的Resource,与宿主隔离

创建新的AssetManager实例,再反射调用AssetManager的addAssetPath方法来加载插件,然后反射得到mAssets属性,把之前新建的AssetManager实例进行动态替换。

动态库的替换

Android平台动态链接库主要指的就是so文件。那也不难理解这类的热更新主要就是重新加载替换的so库。主要用到了System的load和loadLibrary方法

主流的热修复框架类型

(1)ClassLoader:将热修复的类放在dexElements[]的最前面,这样加载类时会优先加载到要修复的类以达到修复目的。如腾讯的Tinker、Nuwa等。

(2)Native hook:修改java方法在native层的函数指针,指向修复后的方法以达到修复目的。如阿里的Andifix、DexPosed等。

(3)Instant run:在编译打包阶段对每个函数都插入一段控制逻辑代码。如美团Robus

(1)Qzone热更新原理

Android热更新六:Qzone热更新原理 - 简书

超级补丁技术基于DEX分包方案,使用了多DEX加载的原理,大致的过程就是:把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。

修复的步骤为:

  1. 可以看出是通过获取到当前应用的Classloader,即为BaseDexClassloader
  2. 通过反射获取到他的DexPathList属性对象pathList
  3. 通过反射调用pathList的dexElements方法把patch.dex转化为Element[]
  4. 两个Element[]进行合并,把patch.dex放到最前面去
  5. 加载Element[],达到修复目的

优势:

没有合成整包(和微信Tinker比起来),产物比较小,比较灵活
可以实现类替换,兼容性高。(某些三星手机不起作用)

不足:

  1. 不支持即时生效,必须通过重启才能生效。
  2. 为了实现修复这个过程,必须在应用中加入两个dex!dalvikhack.dex中只有一个类,对性能影响不大,但是对于patch.dex来说,修复的类到了一定数量,就需要花不少的时间加载。对手淘这种航母级应用来说,启动耗时增加2s以上是不能够接受的事。
  3. 在ART模式下,如果类修改了结构,就会出现内存错乱的问题。为了解决这个问题,就必须把所有相关的调用类、父类子类等等全部加载到patch.dex中,导致补丁包异常的大,进一步增加应用启动加载的时候,耗时更加严重。

(2)AndFix热更新原理

阿里百川推出的热修复HotFix服务,相对于QQ空间超级补丁技术和微信Tinker来说,定位于紧急BUG修复的场景下,能够最及时的修复BUG,下拉补丁立即生效无需等待。

AndFix实现原理:

AndFix不同于QQ空间超级补丁技术和微信Tinker通过增加或替换整个DEX的方案,提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启,对应用无性能消耗的目的。

AndFix实现过程

对于实现方法的替换,需要在Native层操作,经过三个步骤:

Android热修复之AndFix原理探索(黑科技热修复的Java层实现)_amurocrash的博客-CSDN博客_andfix原理

汇编语言的call和ret指令是如何实现类似函数功能的,调用时寄存器的数据是如何压栈保护的。
这里为了方便大家理解,我用一句话来概括AndFix原理的本质:对于计算机来说,一切都只是内存中的数据而已,所以函数也只是内存中的一块数据,方法B替换方法A,其实就是把B中的内容复制到地址A去。
ok,明白了这个我们再去理解代码就轻松多了,先看下方法替换的大致流程:

这里写图片描述

(3)Robust原理分析

【Android】美团robust原理分析_87now的博客-CSDN博客_robust原理

美团Robust实践—原理篇 - 简书

原理:在class转dex的过程中会调用Transform,在该时机修改class对象,完成代码的注入。为每个类插入一个ChangeQuickRedirect类型的静态变量,当这个字段为空时,执行旧的方法,不为空时,就可以对badMethod做拦截,执行新的逻辑,替代掉badMethod,从而达到修复的目的。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐