目前Android热修复的技术方案大致可以归类为以下几种:
- 资源热替换
- 代码热修复
- 动态库替换
资源修复
- 创建新的AssetManager实例,利用反射加载外部(SD卡)需要热修复的资源路径
- 通过当前Activity实例获取Resouces资源类,然后反射得到mAssets属性,把之前新建的AssetManager实例进行动态替换
代码热修复
代码热修复方案可以归纳为以下3种:类加载方案、底层替换方案、Instant Run方案
1、类加载方案
如果你清楚Android的类加载机制,你一定知道DexPathList.java这个类,本节类加载方案主要就是基于DexPathList.java的findClass方法处理逻辑再利用类加载机制的双亲委托模型来实现Bug类的动态修复
2、底层替换方案
与类加载方案不同的是,底层替换方案不会再次加载新类,而是直接在Native层修改原有的类,使其功能立即生效。
拿方法替换来说,我们的方法在ART虚拟机中都对应着一个ArtMethod结构体
3、Instant Run方案
这个也是借鉴了Instant Run里的ASM动态注入技术。什么是ASM?ASM是一个Java字节码操控框架,它能够动态的生成类或者增强类的实现。ASM可以直接生成class文件,也可以在类被加载到虚拟机之前动态的改变类的行为。
动态库的替换
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数组的最前面,让虚拟机去加载修复完后的方法。
修复的步骤为:
- 可以看出是通过获取到当前应用的Classloader,即为BaseDexClassloader
- 通过反射获取到他的DexPathList属性对象pathList
- 通过反射调用pathList的dexElements方法把patch.dex转化为Element[]
- 两个Element[]进行合并,把patch.dex放到最前面去
- 加载Element[],达到修复目的
优势:
没有合成整包(和微信Tinker比起来),产物比较小,比较灵活
可以实现类替换,兼容性高。(某些三星手机不起作用)
不足:
- 不支持即时生效,必须通过重启才能生效。
- 为了实现修复这个过程,必须在应用中加入两个dex!dalvikhack.dex中只有一个类,对性能影响不大,但是对于patch.dex来说,修复的类到了一定数量,就需要花不少的时间加载。对手淘这种航母级应用来说,启动耗时增加2s以上是不能够接受的事。
- 在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,从而达到修复的目的。