AutoPatch java_Android热更新九:Robust热更新原理

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

Robust是美团点评团队在2017年3月开源的热修复框架,和阿里的AndFix不同,Robust不用依赖JNI层,直接通过Java层代码就可以实现热修复。相比于其他热修复框架,官方给出Robust的优势有以下几点

支持Android2.3-7.X版本

高兼容性、高稳定性,修复成功率高达三个九

补丁下发立即生效,不需要重新启动

支持方法级别的修复,包括静态方法

支持增加方法和类

支持ProGuard的混淆、内联、优化等操作

不接触JNI层,Robust是如何添加方法与类、立即生效其补丁的呢?

Robust一共分为四个模块,分别为:

autopatchbase(热补丁基类)

gradle-plugin(负责apk包的插桩)

auto-patch-plugin(负责提取制作patch包)

patch(负责补丁包的补丁工作)

我们一个一个来分析

AutoPatchBase

作为热补丁的基类,主要类是有几个:

2个注解分别为@Add(添加新的类)和@Modify(修改当前类的方法);

一个Constant类用来保存固定的字符串;

一个ChangeQuickRedirect接口,用来给plugin确认当前类是否需要patch

Gradle-Plugin

用于插桩的工具。首先进行对Apk检查防止包被篡改,然后在RobustTransform.groovy中

执行apply(...)方法,读取项目目录下的robust.xml加载热补丁的配置

进入transform(...)方法,依次读取bootClasspath下的所有class文件并加入ClassPool中

进入insertRobustCode方法,然后做了以下几件微小的工作:

将class设置为public

当class为接口/无方法类时,执行5

给class插入一个public static的ChangeQuickRedirect对象

对所有方法使用Javassist插入代码:当该方法的changeQuickRedirect不为空时,直接将参数直接传入PatchProxy的accessDispatchVoid/accessDispatch方法并返回, 这样做跳过了原方法后面的代码,从而实现了方法的替换

写入原来的class文件中

打包压缩生成apk

由此,就实现了插桩的工作

Auto-Patch-Plugin

制作patch包的工具。主要逻辑在AutoPatchTransform.groovy中,

执行apply(…)方法,初始化参数

跳到transform(…)中,又做了细微的工作

复制项目中的LIB_NAME_ARRAY中的3个jar包到./robust/文件夹下(unknown why)

读取bootClasspath路径下的class文件并转换为CtClass对象数组

执行打包autoPatch(…)

首先执行ReadAnnonation(…)去读取CtClass数组中的注解,然后把注解的方法/类放在Config中保存

执行ReadMapping.initMappingInfo(),读取mapping.txt将被ProGuard混淆了的类的对象还原成原来的类

通过InlineClassFactory构造新加的类

处理super的方法调用

针对每一个有补丁方法的类,使用PatchesFactory.createPatch构造出Patch实现类

使用PatchesControlFactory.createPatchesControl构造PatchControl类

使用PatchesInfoFactory.createPatchesInfo构造PatchInfo类

重新打包,优化smali

Patch

在activity中,通过执行以下代码运行了补丁

new PatchExecutor(getApplicationContext(),

new PatchManipulateImp(),

new Callback()).start();

PatchExecutor是一个Thread的子类,通过PatchManipulateImp指定的路径去读patch文件,然后给DexClassLoader加载并读取PatchInfo,然后通过PatchInfo中的信息获得需要补丁的类,通过反射修改其changeQuickRedirect对象的值,做到修改函数运行的路径

总结

用一张图来总结robust原理

07209d40dd0c

image

当然原理看起来简单,其中还是有很多难点在其中,例如

如何解决patch中涉及到的包访问权限

如何解决super的问题

各位对具体实现有兴趣的,可以通过解压官方demo中的补丁包,用JD-GUI来看看patch包中各种patchInfo、patchControl是如何处理的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值