Android热更新六:Qzone热更新原理

很早之前就想深入的研究和学习一下热修复,由于时间的原因一直拖着,现在才执笔弄起来。


Android而更新系列:
Android热更新一:JAVA的类加载机制
Android热更新二:理解Java反射
Android热更新三:Android类加载机制
Android热更新四:热修复机制
Android热更新五:四大热修复方案分析
Android热更新六:Qzone热更新原理
Android热更新七:Tinker热更新原理
Android热更新八:AndFix热更新原理
Android热更新九:Robust热更新原理
Android热更新十:自己写一个Android热修复


  超级补丁技术基于DEX分包方案,使用了多DEX加载的原理,大致的过程就是:把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。


Android热更新六:Qzone热更新原理_第1张图片

  当patch.dex中包含Test.class时就会优先加载,在后续的DEX中遇到Test.class的话就会直接返回而不去加载,这样就达到了修复的目的。

  但是有一个问题是,当两个调用关系的类不在同一个DEX时,就会产生异常报错。我们知道,在APK安装时,虚拟机需要将classes.dex优化成odex文件,然后才会执行。在这个过程中,会进行类的verify操作,如果调用关系的类都在同一个DEX中的话就会被打上CLASS_ISPREVERIFIED的标志,然后才会写入odex文件。

  所以,为了可以正常地进行打补丁修复,必须避免类被打上CLASS_ISPREVERIFIED标志,具体的做法就是单独放一个类在另外DEX中,让其他类调用。

  我们来逆向手机QQ空间APK看一下具体的实现:

  先进入程序入口QZoneRealApplication,在attachBaseContext中进行了两步操作:修复CLASS_ISPREVERIFIED标志导致的unexpected DEX problem异常、加载修复的DEX。

Android热更新六:Qzone热更新原理_第2张图片

1. 修复Unexpected DEX Problem异常

  先看代码,


  可以看到,这里是要加载一个libs目录下的dalvikhack.jar。在项目的assets/libs找到该文件,解压得到’classes.dex’文件,逆向打开该DEX文件,


  通过不同的DEX加载进来,然后在每一个类的构造方法中引用其他DEX中的唯一类AnitLazyLoad,避免类被打上CLASS_ISPREVERIFIED标志。


Android热更新六:Qzone热更新原理_第3张图片

  在无修复的情况下,将DO_VERIFY_CLASSES设置为false,以提高性能。只有在需要修复的时候,才设置为true。


  至于如何加载进来,与下面第二个步骤基本相同。

2. 加载修复的DEX

  从loadPatchDex()方法进入,经过几次跳转,到达核心的代码段,SystemClassLoaderInjector.c()。由于进行了混淆和多次方法的跳转,于是将核心代码段做了如下整理:

Android热更新六:Qzone热更新原理_第4张图片

修复的步骤为:

  1. 可以看出是通过获取到当前应用的Classloader,即为BaseDexClassloader
  2. 通过反射获取到他的DexPathList属性对象pathList
  3. 通过反射调用pathList的dexElements方法把patch.dex转化为Element[]
  4. 两个Element[]进行合并,把patch.dex放到最前面去
  5. 加载Element[],达到修复目的

整体的流程图如下:


Android热更新六:Qzone热更新原理_第5张图片

  从流程图来看,可以很明显的找到这种方式的特点:

优势:

没有合成整包(和微信Tinker比起来),产物比较小,比较灵活
可以实现类替换,兼容性高。(某些三星手机不起作用)

不足:
  1. 不支持即时生效,必须通过重启才能生效。
  2. 为了实现修复这个过程,必须在应用中加入两个dex!dalvikhack.dex中只有一个类,对性能影响不大,但是对于patch.dex来说,修复的类到了一定数量,就需要花不少的时间加载。对手淘这种航母级应用来说,启动耗时增加2s以上是不能够接受的事。
  3. 在ART模式下,如果类修改了结构,就会出现内存错乱的问题。为了解决这个问题,就必须把所有相关的调用类、父类子类等等全部加载到patch.dex中,导致补丁包异常的大,进一步增加应用启动加载的时候,耗时更加严重。

你可能感兴趣的:(Android热更新六:Qzone热更新原理)