sophix热修复技术了解


这个是阿里的热修复技术
官方文档

简单理解热修复

在这里插入图片描述
在这里插入图片描述
优势:

  1. 无需重新发布版本,实时修复
  2. 用户无感知修复,无需重新下载应用
  3. 成功率高,把损失降到最低

可以修复的包括:代码修复,资源修复,so库修复

设计理念

有两个apk,一个是已安装的旧的apk,一个是现在开发已修复bug的新apk,通过工具,根据这两个apk生成补丁。把这个补丁发送给用户,已安装的旧apk会自动安装补丁,使用和新apk一样

Andfix

一般的(其他的)修复方式是需要重启的,因为:在app已经运行后,相关的类信息已经加载到了内存中,程序运行时,会去内存中获取加载的类信息来使用。即使有新的类在这时候载入内存,老的也存在,拿到的还是老的。只有重启后,会把补丁中的新类加载到内存中,替换掉老的类,从而实现热修复。

Andfix的即时生效

Andfix热修复是即时生效,无需重启的。就像电脑换零件,老的是需要你更换后重新启动才有效的。而Andfix是即插即用的

但是Andfix只能做代码修复,而sophix可以实现资源和so库修复。

Andfix与Art

Android4.4以上使用的是Art虚拟机。

ArtMethod

每一个已加载的Java方法在Art虚拟机中,对应一个artMethod,这个artMethod记录了这个Java方法相关的信息,比如所属类,访问权限,代码地址等。

在这里插入图片描述
art虚拟机通过读取artMethod来执行代码的调用

我们可以这么认为,artMethod是一个存储键值对的文件,art虚拟机读取这个键值对文件,来获取要执行代码的地址或者成员的值。

artMethod其实在art虚拟机中是有一个结构的。这个结构由跨源代码,也就是AOSP来决定

Andfix也自己构造了一个artMethod的结构,Andfix的artMethod结构与AOSP开源代码里是完全一致的,而AOSP里的artMethod结构决定了art虚拟机生成的artMethod结构,也就是说,此时,Andfix=AOSP=art虚拟机,他们三个的artMethod结构一致。

  • 但是:
  • AOSP是手机厂商可以更改的,所以生成的虚拟机的artMethod是不定的,造成Andfix内部写定的ArtMethod就可能是不兼容的。比如它不兼容的部分机型

举个例子

就像上面的图一样,这里有一列箱子,每个箱子就是一个artMethod,内部是一层一层的结构存放东西的。而Andfix就是一个神偷,他有个和artMethod结构一样的箱子,他找到自己要偷换的箱子,把自己箱子的东西,放到那个artMethod的箱子里面,层是对应的。

但是如果这个artMethod箱子是格子的方式的,那么这个神偷就没办法对应偷换东西了,他不知道怎么来存放自己的东西
在这里插入图片描述

结构一样的情况下知道怎么去偷换,结构不一样就不知道怎么偷换了

解决兼容问题

解决兼容问题就是,我不管你箱子内部是什么结构了,管你是层的还是格子的,我直接把你整个箱子都换了,来个“偷梁换柱”。你拿到的就是我换上去的箱子。

这其中的关键在于箱子是要一样大的,你不能放个过大的箱子或者过小的箱子,都会有问题

关键代码是:memcpy(smeth,dmeth,sizeof(AreMethod))

其他问题

访问权限问题

  1. 被替换的方法和新的方法属于同一个类,那么机器码是不会进行权限检查的

  2. 假设补丁中的某个类要访问非补丁,同包名下的另一个类的时候,是会报错的,虽然拥有相同的包名,但是是不同的classLoader加载的,虚拟机会对这个classLoader进行判断,书中提到的解决方式是通过反射进行classLoader的设置:

     try {
         Field classLoaderFiled = Class.class.getDeclaredField("classLoader");
         classLoaderFiled.setAccessible(true);
         // 设置新类的classLoader与老的类的classLoader一致
         classLoaderFiled.set(newClass, oldClass.getClassLoader());
     } catch (NoSuchFieldException e) {
         e.printStackTrace();
     }
    

也就是我们要把补丁类的加载器设置为同包名下要访问的类的加载器。

反射调用非静态方法问题

假设我们替换了一个方法A,如果这个A被反射调用,那么会抛出异常。这种异常,书中说用冷启动的方式解决。

  • 热启动:后台运行,未被杀死,再次打开
  • 冷启动:后台杀死,再次启动

即时生效带来的限制

补丁类与原类的成员与方法数需要是一致的。如果增加或者减少,都会造成方法索引变化,从而无法通过索引找到正确的方法。

注意这里说的是类,而上面说偷换的是artMethod。我们假设一个类中的方法对应的artMethod是一个列表,你增加或者减少方法都会造成areMethod列表索引变化,从而找不到对应的方法。

新增或者减少字段,影响也是一样的

但是新增一个类,不会产生这种问题

总结下来,两种情况不适用:

  1. 引起原有类结构变化的时候,不适用
  2. 非静态方法被反射调用

也就是说,sophix的代码修复部分还是借鉴或者说基于Andfix的。

发布了127 篇原创文章 · 获赞 3 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u010513497/article/details/103161864