Android热修复原理

故事扮演 提交于 2020-07-27 13:04:44

AndFix:阿里

Tinker:微信

Qzone:QQ空间

Robust:美团

一、AndFix 采用的是底层替换方案,类似反射

不同:

AndFix 采用的是替换ArtMethod结构体中的字段 所有信息,包括执行入口、访问权限、所属类和代码执行地址等等 ,这样会有兼容问题,因为厂商可能会修改ArtMethod结构体,导致方法替换失败。AndFix采用native。

阿里的Sophix 采用的是替换整个ArtMethod结构体,这样不会存在兼容问题。

缺点: 由于它并没有整体替换class, 而field在class中的相对地址在class加载时已确定,所以AndFix无法支持新增或者删除filed的情况 (只能修改值)

使用:在Application.onCreate() 中添加以下代码

二、Qzone(Dex插桩)、Tinker:类替换

类的加载机制:

类的加载ClassLoader(KitKat - 4.4.4_r1):

parent为BootClassLoader,双亲(我理解为2个亲戚)委托机制,父加载器不是父类

Qzone和Tinker的热修复方案:

第二个参数是dex文件的保存目录

自定义Tinker实现的适配:

v14、V19、V23的区别是Android api参数个数这些修改后反射要做适配

Android N以上Tinker要做适配,官方有发布文档(自定义ClassLoader替换系统分发加载任务的适配器DispatchClassLoader)

不同:

Qzone采用把修复的dex插到最前面实现,但这样会有CLASS_ISPREVERIFIED验证问题(一个dex内的方法与其他dex没有联系就会打上该标记))

缺点: Android系统的这些检查规则是非常有意义的,这会导致QZone方案在Dalvik(启动、加载时长变长)与Art(包体积增大)都会产生一些问题。

Tinker是将完整包插入到最前面,为了解决patch包太大的问题,每次生成差分包下载后与原APP合成完整包再插入

类加载方案基于Dex分包方案

65536限制DVM指令集的方法调用指令invoke-kind索引为16bits 最多能引用 65535个方法 (2^16)。

LinearAlloc限制:在安装时可能会提示INSTALL_FAILED_DEXOPT。DVM中的LinearAlloc是一个固定的缓存区,当方法数过多超出了缓存区的大小时会报错。

为了解决65536限制和LinearAlloc限制,从而产生了Dex分包方案。Dex分包方案主要做的是在打包时将应用代码分成多个Dex,将应用启动时必须用到的类和这些类的直接引用类放到主Dex中,其他代码放到次Dex中。当应用启动时先加载主Dex,等到应用启动后再动态的加载次Dex,从而缓解了主Dex的65536限制和LinearAlloc限制。

缺点:不能即时生效

三、Robust( Instant Run原理 ):热插拔 成功率最高

普通的类是这样:

Robust将每个类插入一段代码:

源码:

客户端拿到patch.dex后,用DexClassLoader加载patch.dex,反射拿到class。拿到后,创建这个class的一个对象。然后通过这个对象的getPatchedClassesInfo函数,知道需要patch的class为com.meituan.sample.d(com.meituan.sample.State混淆后的名字),再反射得到当前运行环境中的com.meituan.sample.d class,将其中的changeQuickRedirect字段赋值为用patch.dex中的StatePatch.java这个class new出来的对象。这就是打patch的主要过程。

补丁结构:每个补丁包含以下三个部分

  • PatchesInfoImplimplements PatchesInfo :补丁包说明类,可以获取所有补丁对象;每个对象包含被修复类名及该类对应的补丁类。
  • PatchControlimplements ChangeQuickRedirect :补丁类,具备判断方法是否执行补丁逻辑,及补丁方法的调度。
  • Patch:具体补丁方法的实现。该类中包含被修复类中需要热修的方法。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!