美文网首页
简单了解Robust(一)

简单了解Robust(一)

作者: _夜雨 | 来源:发表于2018-02-28 16:32 被阅读181次

    因为工作需要,所以需要在公司项目中增加Robust补丁,其实操作流程很简单,只是对其中原理不是很理解,下面简单看一下生成的文件:

    一、首先看一下添加Robust依赖之后生成的apk文件的代码:

    线上apk经过Robust的代码

    经过查看可以了解到,Robust给每一个类(另一个MainActivity类也增加了)增加了一个叫做ChangeQuickRedirect的静态变量,然后在每一个方法的最前面增加了一段代码,目前我们还不知道这段代码的含义,但是大概知道,如果能够PatchProxy.isSuuport()为true的话,那么就不走原来的逻辑,而是直接走插桩代码的逻辑。

    下面简单看一下PatchProxy.isSupport里面有什么:

    PatchProxy.isSupport() PatchProxy.accessDispatch()

    经过上面代码,其实主要有两个疑问:

    - 如何将那一段插桩代码插入进去?

    - 每个类中都会插入一个ChangeQuickRedirect静态变量,在走到具体方法时,会在isSupport里面判断该变量是否为空,那么是什么时候对这个ChangeQuickRedirect变量赋值的呢?

    二、下面看一下补丁patch.jar(patch.dex)代码:

    打开之后一共有三个类:

    1、PatchesInfoImpl类:

    可以看到里面逻辑很简单,是将待修复的方法所在类与另一个XXXXPatchControl类放进了集合:

    PatchesInfoImpl类

    2、下面看一下SecondActivityPatchControl类:

    首先可以看到这个类实现了ChangeQuickRedirect接口,并重写了isSupport和accessDispatch方法:

    补丁类

    重写了isSupport方法:(内部逻辑没太看懂,但是应该只是判断一下当前方法是不是要fix的那个方法,需要去撸源码看一下)

    重写isSupport方法

    重写了accessDispatch方法,因为是反编译代码,所以其实没太看懂,但是起码可以看到重新new了SecondActivityPatch对象,并且执行了其中的fix方法,所以应该来说最终真正的补丁后的方法在SecondActivityPatch中:

    重写accessDispatch方法

    3、下面看一下最后一个类:SecondActivityPatch

    fix之后的逻辑

    看完了上面补丁里面的代码,其实还是有一个最开始的疑问,这个patch补丁是如何加载以及生效的?因为代码被混淆,我们只好去看一下Robust的wiki:

    wiki说明是因为如何加载需要开发者自定义,因此官方给出了一个demo,在demo中可以看到,逻辑比较简单,主要有两步:

    (1)、联网下载补丁;

    (2)、使用DexClassLoader加载patch补丁,加载时,首先反射获取com.meituan.robust.patch.PatchesInfoImpl的对应的Class对象,通过调用其中的getPatchedClassesInfo()方法来查看哪些类有修改,获取patchClass以及oldClass,同时使用反射修改oldClass中对应的变量值ChangeQuickRedirect,改成XXXXPatchControl对应的Class对象,从而保证patch设置的状态成功;

    加载补丁dex并修改oldClass中静态变量的对象

    三、通过上面的逻辑梳理,基本可以确定Robust逻辑是这样的:

    1、在编译时候通过Gradle插件或者AOP对每一个类的每个方法进入了代码插桩,插入固定的一段代码,并给每一个类都添加一个ChangeQuickRedirect静态变量;

    2、通过对需要fix的方法增加注解,然后生成Patch补丁,补丁中包含三个类:

    - PatchesInfoImpl:包含oldClass类名以及patchClass类名,放入集合;

    - XXXXPatch:fix之后的方法放进了这个类,不会处理其他逻辑;

    - XXXXPatchControl:实现了ChangeQuickRedirect接口,其实是XXXXPatch类的代理,重写isSupport和accessDispatch方法,在accessDispatch方法中会进入XXXXPatch类的fix之后的方法;

    3、启动apk之后,下发patch补丁,使用类加载器加载补丁,同时读取PatchesInfoImpl类中的oldClass以及PatchClass,修改oldClass中的ChangeQuickRedirect变量,指向为XXXXPatchControl对象;

    4、走到等待fix的方法时,因为此方法待fix,所以会直接走进ChangeQuickRedirect的实现类XXXXPatchControl类,同时执行对应的accessDispatch方法,从而最终执行XXXXPatch的对应方法。

    其实官方图画的相当清楚:

    官方Robust图

    四、虽然整体的流程大概明白,但是其中有很多疑问没有解决:

    1、如何插桩那一段代码?(ASM ?Javassist?)

    2、补丁如何自动生成?

    3、如何能够准确找到每一个方法?以及下面这一句代码的具体含义?

    原始代码:

    isSupport原始代码 isSupport反编译效果

    相关文章

      网友评论

          本文标题:简单了解Robust(一)

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