robust原理解析

robust原理解析
接上一篇
robust使用

打基础包的时候,每个类都会被添加

public static ChangeQuickRedirect u;静态成员变量

查看这个类的源码发现这个是一个接口

public interface ChangeQuickRedirect {
    Object accessDispatch(String methodName, Object[] paramArrayOfObject);

    boolean isSupport(String methodName, Object[] paramArrayOfObject);
}

反编译基本包能看到每个方法当中都被添加了这个判断
在这里插入图片描述

 public static PatchProxyResult proxy(Object[
 
 ] paramsArray, Object current, ChangeQuickRedirect changeQuickRedirect, boolean isStatic, int methodNumber, Class[] paramsClassTypes, Class returnType) {
        PatchProxyResult patchProxyResult = new PatchProxyResult();
        if (PatchProxy.isSupport(paramsArray, current, changeQuickRedirect, isStatic, methodNumber, paramsClassTypes, returnType)) {
            patchProxyResult.isSupported = true;
            patchProxyResult.result = PatchProxy.accessDispatch(paramsArray, current, changeQuickRedirect, isStatic, methodNumber, paramsClassTypes, returnType);
        }
        return patchProxyResult;
    }

    public static boolean isSupport(Object[] paramsArray, Object current, ChangeQuickRedirect changeQuickRedirect, boolean isStatic, int methodNumber, Class[] paramsClassTypes, Class returnType) {
        //Robust补丁优先执行,其他功能靠后
        if (changeQuickRedirect == null) {
            //不执行补丁,轮询其他监听者
            if (registerExtensionList == null || registerExtensionList.isEmpty()) {
                return false;
            }
            for (RobustExtension robustExtension : registerExtensionList) {
                if (robustExtension.isSupport(new RobustArguments(paramsArray, current, isStatic, methodNumber, paramsClassTypes, returnType))) {
                    robustExtensionThreadLocal.set(robustExtension);
                    return true;
                }
            }
            return false;
        }
        String classMethod = getClassMethod(isStatic, methodNumber);
        if (TextUtils.isEmpty(classMethod)) {
            return false;
        }
        Object[] objects = getObjects(paramsArray, current, isStatic);
        try {
            return changeQuickRedirect.isSupport(classMethod, objects);
        } catch (Throwable t) {
            return false;
        }
    }
 

如果PatchProxy.isSupport返回true

就执行PatchProxy.accessDispatch

查看源码

public static Object accessDispatch(Object[] paramsArray, Object current, ChangeQuickRedirect changeQuickRedirect, boolean isStatic, int methodNumber, Class[] paramsClassTypes, Class returnType) {

        if (changeQuickRedirect == null) {
            RobustExtension robustExtension = robustExtensionThreadLocal.get();
            robustExtensionThreadLocal.remove();
            if (robustExtension != null) {
                notify(robustExtension.describeSelfFunction());
                return robustExtension.accessDispatch(new RobustArguments(paramsArray, current, isStatic, methodNumber, paramsClassTypes, returnType));
            }
            return null;
        }
        String classMethod = getClassMethod(isStatic, methodNumber);
        if (TextUtils.isEmpty(classMethod)) {
            return null;
        }
        notify(Constants.PATCH_EXECUTE);
        Object[] objects = getObjects(paramsArray, current, isStatic);
        return changeQuickRedirect.accessDispatch(classMethod, objects);
    }

最后调用的就是changeQuickRedirect的accessDispatch

那实际调用的就是这个接口的实现类的方法

接下来看补丁文件

PatchesInfoImpl

根据我的上篇使用文章,我反编译出patchesinfoimpl的代码为

public class PatchesInfoImpl implements PatchesInfo {
  public List getPatchedClassesInfo() {
    ArrayList<PatchedClassInfo> arrayList = new ArrayList();
    arrayList.add(new PatchedClassInfo("com.freebrio.robustdemo.MainActivity", "com.freebrio.robustdemo.MainActivityPatchControl"));
    EnhancedRobustUtils.isThrowable = false;
    return arrayList;
  }
}

里面列出了我修改的类和对应的修改方法

MainActivity ->MainActivityPatchControl

打开这个类

package com.freebrio.robustdemo;

import android.view.View;
import com.meituan.robust.ChangeQuickRedirect;
import java.util.Map;
import java.util.WeakHashMap;

public class MainActivityPatchControl implements ChangeQuickRedirect {
  public static final String MATCH_ALL_PARAMETER = "(\\w*\\.)*\\w*";
  
  private static final Map<Object, Object> keyToValueRelation = new WeakHashMap<Object, Object>();
  
  private static Object fixObj(Object paramObject) {
    Object object = paramObject;
    if (paramObject instanceof Byte) {
      boolean bool;
      if (((Byte)paramObject).byteValue() != 0) {
        bool = true;
      } else {
        bool = false;
      } 
      object = new Boolean(bool);
    } 
    return object;
  }
  
  public Object accessDispatch(String paramString, Object[] paramArrayOfObject) {
    try {
      MainActivityPatch mainActivityPatch;
      if (paramString.split(":")[2].equals("false")) {
        if (keyToValueRelation.get(paramArrayOfObject[paramArrayOfObject.length - 1]) == null) {
          mainActivityPatch = new MainActivityPatch(paramArrayOfObject[paramArrayOfObject.length - 1]);
          keyToValueRelation.put(paramArrayOfObject[paramArrayOfObject.length - 1], null);
        } else {
          mainActivityPatch = (MainActivityPatch)keyToValueRelation.get(paramArrayOfObject[paramArrayOfObject.length - 1]);
        } 
      } else {
        mainActivityPatch = new MainActivityPatch(null);
      } 
      if ("5".equals(paramString.split(":")[3])) {
        mainActivityPatch.setTV((View)paramArrayOfObject[0]);
        return null;
      } 
    } catch (Throwable throwable) {
      throwable.printStackTrace();
      return null;
    } 
    return null;
  }
  
  public Object getRealParameter(Object paramObject) {
    Object object = paramObject;
    if (paramObject instanceof MainActivity)
      object = new MainActivityPatch(paramObject); 
    return object;
  }
  
  public boolean isSupport(String paramString, Object[] paramArrayOfObject) {
    paramString = paramString.split(":")[3];
    return ":5:".contains(":" + paramString + ":");
  }
}

他实现的就是ChangeQuickRedirect

也就是说如果ChangeQuickRedirect不等于null那就会执行MainActivityPatchControl中的accessDispatch

可以看到这一行关键代码

if ("5".equals(paramString.split(":")[3])) {
        mainActivityPatch.setTV((View)paramArrayOfObject[0]);
        return null;
      } 

在mainactivitypatch的settv方法中

public final void setTV(View paramView) {
    MainActivityPatch mainActivityPatch;
    MainActivity mainActivity1;
    CharSequence charSequence;
    MainActivity mainActivity2;
    new IntrinsicsInLinePatch(getRealParameter(new Object[] { null })[0]);
    EnhancedRobustUtils.invokeReflectStaticMethod("checkParameterIsNotNull", IntrinsicsInLinePatch.class, getRealParameter(new Object[] { paramView, "view" }, ), new Class[] { Object.class, String.class });
    if (this instanceof MainActivityPatch) {
      mainActivity1 = this.originClass;
    } else {
      mainActivityPatch = this;
    } 
    TextView textView2 = (TextView)EnhancedRobustUtils.getFieldValue("q", mainActivityPatch, MainActivity.class);
    if (textView2 == null) {
      new IntrinsicsInLinePatch(getRealParameter(new Object[] { null })[0]);
      EnhancedRobustUtils.invokeReflectStaticMethod("throwUninitializedPropertyAccessException", IntrinsicsInLinePatch.class, getRealParameter(new Object[] { "textView" }, ), new Class[] { String.class });
    } 
    String str = (String)EnhancedRobustUtils.invokeReflectMethod("getString1", new MainActivityInLinePatch(getRealParameter(new Object[] { this }, )[0]), getRealParameter(new Object[0]), null, null);
    if (str == this) {
      mainActivity1 = ((MainActivityPatch)str).originClass;
    } else {
      charSequence = (CharSequence)mainActivity1;
    } 
    TextView textView1 = textView2;
    if (textView2 == this)
      mainActivity2 = ((MainActivityPatch)textView2).originClass; 
    EnhancedRobustUtils.invokeReflectMethod("setText", mainActivity2, getRealParameter(new Object[] { charSequence }, ), new Class[] { CharSequence.class }, TextView.class);
  }

可以看到这一行关键代码

String str = (String)EnhancedRobustUtils.invokeReflectMethod("getString1", new MainActivityInLinePatch(getRealParameter(new Object[] { this }, )[0]), getRealParameter(new Object[0]), null, null);

最后调用的是我修改后的getString1方法,达到了修复的目的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-894ebPHj-1619509516136)(/Users/yanzhe/android/知识整理/image/image-20210427145541550.png)]

接下来看一下加载过程

new PatchExecutor(getApplicationContext(), new PatchManipulateImp(),  new Callback()).start();

在PatchExecutor的patch方法中


ClassLoader classLoader = null;

        try {
            File dexOutputDir = getPatchCacheDirPath(context, patch.getName() + patch.getMd5());
            classLoader = new DexClassLoader(patch.getTempPath(), dexOutputDir.getAbsolutePath(),
                    null, PatchExecutor.class.getClassLoader());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        if (null == classLoader) {
            return false;
        }
        
        
try {
            Log.d("robust", "patch patch_info_name:" + patch.getPatchesInfoImplClassFullName());
            patchesInfoClass = classLoader.loadClass(patch.getPatchesInfoImplClassFullName());
            patchesInfo = (PatchesInfo) patchesInfoClass.newInstance();
        } catch (Throwable t) {
            Log.e("robust", "patch failed 188 ", t);
        }
        
        
         Field[] fields = sourceClass.getDeclaredFields();
                Log.d("robust", "oldClass :" + sourceClass + "     fields " + fields.length);
                Field changeQuickRedirectField = null;
                for (Field field : fields) {
                    if (TextUtils.equals(field.getType().getCanonicalName(), ChangeQuickRedirect.class.getCanonicalName()) && TextUtils.equals(field.getDeclaringClass().getCanonicalName(), sourceClass.getCanonicalName())) {
                        changeQuickRedirectField = field;
                        break;
                    }
                }

创建了DexClassLoader,根据dexclassloader去加载dex文件,

classLoader.loadClass(patch.getPatchesInfoImplClassFullName())

getPatchesInfoImplClassFullName就是PatchesInfoImpl类,里面记录了修改的类的信息

加载完类之后

changeQuickRedirectField = field;将这个静态变量赋值接下来就走上面的步骤了

插件代码

https://github.com/Meituan-Dianping/Robust/tree/master/gradle-plugin

用AsmInsertImpl和JavaAssistInsertImpl

插桩核心代码

createInsertCode

位于https://github.com/Meituan-Dianping/Robust/blob/master/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/RobustAsmUtils.java

类中

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值