美文网首页
Tinker热修复原理

Tinker热修复原理

作者: 禅座 | 来源:发表于2019-06-16 19:05 被阅读0次

    当前市面的热补丁方案有很多,其中比较出名的有阿里的AndFix、美团的Robust以及QZone的超级补丁方案。
    但它们都存在无法解决的问题,这也是正是推荐Tinker的原因。

    Tinker QZone AndFix Robust
    类替换 yes yes no no
    So替换 yes no no no
    资源替换 yes yes no no
    全平台支持 yes yes yes yes
    即时生效 no no yes yes
    性能损耗 较小 较大 较小 较小
    补丁包大小 较小 较大 一般 一般
    开发透明 yes yes no no
    复杂度 较低 较低 复杂 复杂
    gradle支持 yes no no no
    Rom体积 较大 较小 较小 较小
    成功率

    图解修复过程

    image.png

    原理:

    当我们在java代码当中new 一个对象的时候,会通过PathClassLoader去执行类加载工作,但是通过阅读源码发现,PathClassLoader其实只是一个包装类,是不干实事的,最终是通过调用
    BaseDexClassLoader中的PathDexList对象的findClass方法进行加载,而PathDexList中的Elements[]存储的则是我们的dex文件(classes.dex,classes2.dex...)

    public class BaseDexClassLoader extends ClassLoader {
      // 需要加载的dex列表
      private final DexPathList pathList;
      // dexPath要加载的dex文件所在的路径,optimizedDirectory是odex将dexPath
      // 处dex优化后输出到的路径,这个路径必须是手机内部路劲,libraryPath是需要
      // 加载的C/C++库路径,parent是父类加载器对象
      public BaseDexClassLoader(String dexPath, File optimizedDirectory,
              String libraryPath, ClassLoader parent) {
          super(parent);
          this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
      }
    
      @Override
      protected Class<?> findClass(String name) throws ClassNotFoundException {
          List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
          // 使用pathList对象查找name类
          Class c = pathList.findClass(name, suppressedExceptions);
          return c;
      }
    }
    final class DexPathList {
    //在这个地方会遍历我们的Element数组,直到找到我们需要Class
    public Class<?> findClass(String name, List<Throwable> suppressed) {
          for (Element element : dexElements) {
              Class<?> clazz = element.findClass(name, definingContext, suppressed);
              if (clazz != null) {
                  return clazz;
              }
          }
    
          if (dexElementsSuppressedExceptions != null) {
              suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
          }
          return null;
      }
    }
    

    通过DexPathList 的findclass方法,会遍历Elements数组,直到找到我们指定的class。
    热修复便是基于该顺序遍历的方式,通过在Elements的头部插入我们修复好的dex,当我们查找class的时候,由于在Elements头部找到了我们所需的class,后面有问题的便不会进行加载。

    步骤:

    • 将修改好的java文件转为dex包,上传到服务端;
    • app下载好服务端上传的dex包到sd卡目录;
    • 将下载好的dex包转移到odex目录下,同时将其存储到BaseDexClassLoader中的PathDexList对象当中的dexElements数组当中。
    • 结束

    相关文章

      网友评论

          本文标题:Tinker热修复原理

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