美文网首页
热修复研究笔记

热修复研究笔记

作者: 浪里_个郎 | 来源:发表于2020-04-30 15:21 被阅读0次

热修复原理

目前了解的热修复方案有:
从java加载机制入手:腾讯tinker。
从底层二进制入手(c语言):阿里DeXposed、andfix。
物理修改dex文件加载顺序:大众点评Nuwa
博采众长:阿里Sophix

1,java加载机制实现热修复
双亲委托机制图示

1,双亲委托机制保证了类只被加载一次
2,DexClassLoader查找类时,会对之前构造好dexElements数组集合进行遍历,一旦找到类名与name相同的类时,就直接返回这个class,找不到则返回null
3,我们可以在修复完bug之后,可以将这些个类打包成一个补丁文件,然后通过这个补丁文件封装出一个Element对象,并且将这个Element对象插到原有dexElements数组的最前端,这样当DexClassLoader去加载类时,优先会从我们插入的这个Element中找到相应的类,虽然那个有bug的类还存在于数组中后面的Element中,但由于双亲加载机制的特点,这个有bug的类已经没有机会被加载了

ClassLoader类图

从上图可以看到,要修改的dexElements,就在加载dex的ClassLoader中。DexClassLoader和PathClassLoader源代码位于AOSP目录的libcore\dalvik\src\main\java\dalvik\system。
PathClassLoader只会加载已安装包中的dex文件,而DexClassLoader不仅仅可以加载dex文件,还可以加载jar、apk、zip文件中的dex。

dex插桩方案实现热修复的代码实现步骤:
1,修改源代码,编译出.class文件 ->
2,连带包文件夹,通过dx命令打包成dex补丁文件。如果要放入jar、apk或zip压缩包,其中的补丁dex必须命名为classes.dex。 ->
3,待热修复的设备下载补丁 ->
4,获取加载目前有问题的dex的ClassLoader ->

//加载应用程序的dex
PathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader();

5,通过new DexClassLoader来加载所有dex补丁 ->

DexClassLoader dexLoader = new DexClassLoader(
                        dex.getAbsolutePath(),// 修复好的dex(补丁)所在目录
                        fopt.getAbsolutePath(),// 存放dex的解压目录(用于jar、zip、apk格式的补丁)
                        null,// 加载dex时需要的库
                        pathLoader// 父类加载器

6,新dex和之前的dex合并dexElements,并赋值给老类加载器的dexElements

        //反射得到新老类加载器中的pathList对象
        Object dexPathList = getField(dexLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
        Object pathList = getField(pathLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
         //反射得到pathList中的dexElements
        Object arrayLhs = getField(dexPathList, dexPathList.getClass(), "dexElements");
        Object arrayRhs = getField(pathList, pathList.getClass(), "dexElements");
        //合并dexElements
        Class<?> componentType = arrayLhs.getClass().getComponentType();
        Object dexElements = Array.newInstance(componentType, k);// 创建一个类型为componentType,长度为k的新数组
        //i,j指代数组长度。新创建的数组,将新老DexElements的数据都拷进去
        System.arraycopy(arrayLhs, 0, result, 0, i);
        System.arraycopy(arrayRhs, 0, result, i, j);
        //反射给老对象中的属性重新赋值
        Field declaredField = pathList.getClass().getDeclaredField("dexElements");
        declaredField.setAccessible(dexElements);
        declaredField.set(pathList, dexElements);

需要保证老的class在修复前并没有被classloader加载,或已经被GC,这样patch中的class才能被classloader正确加载。

2,Native hook实现热修复
阿里Dexposed,Native hook热修复原理

原理简单来说,java层方法的字节码放到内存中后,JVM会查询这块内存,生成ClassObject,其中存放了指向所有这块内存中method的指针集合。通过修改directMethods中需要热修复的method对应的指针insns,就能够将method指向替换进去的,修复了问题的method。

缺点:
Dalvik上近乎完美,不支持ART(需要另外的实现方式),所以5.0以上不能用了;
最大挑战在于稳定性与兼容性,而且native异常排查难度更高;
由于无法增加变量与类等限制,无法做到功能发布级别;
后来阿里又发布了AndFix热修复框架,支持了ART,不过依然存在可能的兼容性问题。

3,物理修改dex文件加载顺序

将老的classes.dex重命名为classes2.dex,将patch dex命名为classes.dex,放入apk中,重启后ART会检查相应DEX文件的CRC32校验和,如果检查发现不对的话,ART就会重新从原有JAR中再度生成OAT,并且patch dex将排在队列最前面,里面的class会最先被加载,从而达到修复的作用。

缺点是必须重启。

3,主流热修复框架原理

AndFix:由补丁类的classLoader加载补丁类,在native层针对不同Android架构中的不同的ArtMethod结构调用对应的replaceMethod方法按照定义好的ArtMethod结构一一替换方法的所有信息如所属类、访问权限、代码内存地址等。
稳定性较差,会受到国内ROM厂商对ArtMethod结构更改的影响,所以这正是AndFix不支持很多机型的原因。

Sophix:由补丁类的classLoader加载补丁类,在native层直接memcpy(smeth,dmth,sizeof(ArtMethod))替换整个artMethod的结构。初始化类时会为这个类分配空间,AllocArtMethodArray会紧挨着的new出来放入art中的方法数组中。通过计算辅助类的前后两个方法的起始地址就可以计算出artMethod结构的大小了。
注:补丁类初始化时,也会分配自己的artMethod空间,拿这个修复过的新ArtMethod去替换旧ArtMethod的内容,不用管ArtMethod的结构。稳定性大大提高!

参考:
热修复——深入浅出原理与实现
干货满满,Android热修复方案介绍
Android热修复技术原理详解

相关文章

  • 热修复研究笔记

    热修复原理 目前了解的热修复方案有:从java加载机制入手:腾讯tinker。从底层二进制入手(c语言):阿里De...

  • 【学习笔记】Android热修复

    【学习笔记】Android热修复 [未完待续] 原文链接-论热修复实战心得—很值得学习的热修复详解|强烈推荐 1....

  • 热修复框架研究

    1. 当前常见热修复框架 基本上只在国内用,国外比较佛系,有错发版改就哦了。就像在国外Kotlin大行其道的时候,...

  • Flutter热修复研究

    一.开发环境: 二.混合开发模式的选择 a.Flutter的产物以aar形式提供给Android使用,实现解耦b....

  • 热修复笔记

    在发布了新版apk后,发现有bug,通常是修复好bug后,经过测试等一系列流程,再发布到各个平台上,这样做特别耗时...

  • 热修复笔记

    Android热修复技术原理详解(最新最全版本) Android 热修复 -- 实现原理 (QQ空间)安卓App热...

  • Tinker接入实现和原理分析

      最近研究了下Tinker的热修复实现,相对于其他的热修复方法,微信的热修复有着不可比拟的用户基数优势,这里也不...

  • 笔记 深入探索Android热修复技术原理

    阿里电子书《深入探索Android热修复技术原理》整理的笔记 1.热修复技术介绍 代码修复两大主要方案底层替换方案...

  • 热修复框架研究之Robust原理(转)

    热修复框架研究之Robust原理 Robust是美团点评团队在2017年3月开源的热修复框架,和阿里的AndFix...

  • Android热修复

    Android热修复笔记java--->class---jar--->dex使用方法:1、运行修复的程序,2、在b...

网友评论

      本文标题:热修复研究笔记

      本文链接:https://www.haomeiwen.com/subject/khdbwhtx.html