Tinker热修复原理

当前市面的热补丁方案有很多,其中比较出名的有阿里的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体积 较大 较小 较小 较小
成功率

图解修复过程

Tinker热修复原理_第1张图片
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 suppressedExceptions = new ArrayList();
      // 使用pathList对象查找name类
      Class c = pathList.findClass(name, suppressedExceptions);
      return c;
  }
}
final class DexPathList {
//在这个地方会遍历我们的Element数组,直到找到我们需要Class
public Class findClass(String name, List 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热修复原理)