三大修复框架比较及DroidFix热修复框架的使用

热修复框架的比较
  1. 热修复作为当下热门的技术,在业界内比较著名的有阿里巴巴的AndFix、Dexposed,腾讯QQ空间的超级补丁和微信的Tinker。
  2. QQ空间的超级补丁热修复框架DroidFix
    超级补丁技术基于DEX分包方案,使用了多DEX加载的原理,大致的过程就是:把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。
    当patch.dex中包含Test.class时就会优先加载,在后续的DEX中遇到Test.class的话就会直接返回而不去加载,这样就达到了修复的目的.
    整体的流程图如下:

    优势:
    没有合成整包(和微信Tinker比起来),产物比较小,比较灵活;
    可以实现类替换,兼容性高。(某些三星手机不起作用);
    不足:
    不支持即时生效,必须通过重启才能生效;
    为了实现修复这个过程,必须在应用中加入两个dex!dalvikhack.dex中只有一个类,对性能影响不大,但是对于patch.dex来说,修复的类到了一定数量,就需要花不少的时间加载。对手淘这种航母级应用来说,启动耗时增加2s以上是不能够接受的事;
    在ART模式下,如果类修改了结构,就会出现内存错乱的问题。为了解决这个问题,就必须把所有相关的调用类、父类子类等等全部加载到patch.dex中,导致补丁包异常的大,进一步增加应用启动加载的时候,耗时更加严重;
  1. 微信热修复框架Tinker
    微信针对QQ空间超级补丁技术的不足提出了一个提供DEX差量包,整体替换DEX的方案。主要的原理是与QQ空间超级补丁技术基本相同,区别在于不再将patch.dex增加到elements数组中,而是差量的方式给出patch.dex,然后将patch.dex与应用的classes.dex合并,然后整体替换掉旧的DEX文件,以达到修复的目的

    整体流程如下:

    优势:
    合成整包,不用在构造函数插入代码,防止verify,verify和opt在编译期间就已经完成,不会在运行期间进行;
    性能提高。兼容性和稳定性比较高;
    开发者透明,不需要对包进行额外处理;
    不足:
    与超级补丁技术一样,不支持即时生效,必须通过重启应用的方式才能生效;
    需要给应用开启新的进程才能进行合并,并且很容易因为内存消耗等原因合并失败;
    合并时占用额外磁盘空间,对于多DEX的应用来说,如果修改了多个DEX文件,就需要下发多个patch.dex与对应的classes.dex进行合并操作时这种情况会更严重,因此合并过程的失败率也会更高

  2. 阿里热修复框架HotFix
    阿里百川推出的热修复HotFix服务,相对于QQ空间超级补丁技术和微信Tinker来说,定位于紧急BUG修复的场景下,能够最及时的修复BUG,下拉补丁立即生效无需等待;AndFix不同于QQ空间超级补丁技术和微信Tinker通过增加或替换整个DEX的方案,提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启,对应用无性能消耗的目的


    优势:
    BUG修复的即时性;
    补丁包同样采用差量技术,生成的PATCH体积小;
    对应用无侵入,几乎无性能损耗
    不足:
    不支持新增字段,以及修改方法,也不支持对资源的替换;
    由于厂商的自定义ROM,对少数机型暂不支持;

总结

QQ空间超级补丁技术和微信Tinker 支持新增类和资源的替换,在一些功能化的更新上更为强大,但对应用的性能和稳定会有的一定的影响;阿里百川HotFix虽然暂时不支持新增类和资源的替换,对新功能的发布也有所限制,但是作为一项定位为线上紧急BUG的热修复的服务来说,能够真正做到BUG即时修复用户无感知,同时保证对应用性能不产生不必要的损耗,在热修复方面不失为一个好的选择

热修复的一些问题
  1. 多DEX带来的性能影响,启动时间过长
    我们知道,多DEX方案原来是用于解决应用方法数65k的问题,现在google也官方支持了MultiDex的实现方案。超级补丁技术和Tinker却作为一种热修复的方案,平生给应用增加了多个DEX,而多DEX技术最大的问题在于性能上的坑,因此基于这种方案的补丁技术影响应用的性能是无疑的;
    我们可以看到,超级补丁技术和Tinker都选择在Application的attachBaseContext()进行补丁dex的加载,即时这是加载dex的最佳时机,但是依然会带来很大的性能问题,首当其冲的就是启动时间太长
    对于补丁DEX来说,应用启动时虚拟机会进行dexopt操作,将patch.dex文件转换成odex文件,这个过程本身非常耗时。而这个过程又要求在主线程中,以同步的方式执行,否则无法成功进行修复
  2. 易造成应用的ANR和Crash
    由于多DEX加载导致了启动时间变长,这样更容易引发应用的ANR。我们知道当应用在主线程等待超过5s以后,就会直接导致长时间无响应而退出。超级补丁技术为保证ART不出现地址错乱问题,需要将所有关联的类全部加入到补丁中,而微信Tinker采取一种差量包合并加载的方式,都会使要加载的DEX体积变得很大。这也很大程度上容易导致ANR情况的出现;
    除了应用ANR以外,多DEX模式也同样很容易导致Crash情况的出现。在ART设备中为了保证不出现地址错乱,需要把修改类的所有相关类全部加入到补丁中,这里会出现一个问题,为了保证补丁包的体积最小,能否保证引入全部的关联类而不引入无关的类呢?一旦没有引入关联的类,就会出现以下的异常;
    · NoClassDefFoundError
    · Could Not Find Class
    · Could Not Find Method
    出现这些异常,就会直接导致应用的Crash退出。
    所以,不难看出如果我们需要修复一个不是Crash的BUG,但是因为未加入相关类而导致了更严重的Crash,就更加的得不偿失
DroidFix热修复框架的使用
  1. Clone框架并将相应的库配置到项目中
    Andrid
  2. 配置工程build.gradle,将DroidFix项目中的build.gradle中的相关的配置复制到自己项目中
    Android
  3. 生成apk文件,打正式包时选择release,打包完成会生成一个DroidPatch文件夹,里面包含有classes.md5.txt,mapping.txt二个文件,这二个文件是在打修复包时会用到,这二个文件要注意保留,因为打修复包是根据这二个文件中的配置来生成patch.apk文件的
    Android
    Android
  4. 打修复包,此时生成的patch.apk文件就热修复的apk,将其放在服务器上然后下载下来就可使用
    Android
  5. 在application中加入相应的代码,在打开app时跟后台交互查看些版本的app是否有patch.apk文件,有则下载下来当下次再打开app时就会加载patch.apk文件到内存,以此达到修复bug的文件
    Android
  6. 注意事项
    此修复办法只能在再次打开app时生效,所以如果用户在一打开app就崩溃时是无法达到修复目的的,因为patch.apk文件还没下载到本地;
    此修复只能针对java文件,不能对资源文件进行修复
参考资料
  1. 热修复原理
  2. DroidFix框架
坚持原创技术分享,您的支持将鼓励我继续创作!