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的主要过程。
补丁结构:每个补丁包含以下三个部分
- PatchesInfoImpl
implements PatchesInfo
:补丁包说明类,可以获取所有补丁对象;每个对象包含被修复类名及该类对应的补丁类。 - PatchControl
implements ChangeQuickRedirect
:补丁类,具备判断方法是否执行补丁逻辑,及补丁方法的调度。 - Patch:具体补丁方法的实现。该类中包含被修复类中需要热修的方法。
来源:oschina
链接:https://my.oschina.net/glfei/blog/4308795