【安卓笔记】,热修复实现2x

发布时间:2022-06-21 12:50:08   来源:党团工作    点击:   
字号:

 【安卓笔记】

 热修复实现 2 热修复实现( 一) 之前也分析过 InstantRun 的源码,前面也写了一篇热修复实现原理的文章。

 But,最近遇到困难了,所在项目要做插件化,同事在开发过程中遇到了一个在5.0 以下手机崩溃的问题,想着一起找找原因修复下。

 但是这个 bug 已经折腾了我两天了,只找到原因,并没有找出任何解决方案

 深深的感觉到之前的那些都是皮毛,没有真正的去做,真正的去处理一些细节,那些都是没任何意义的。

 所以这里系统学习一下,既然学习,就找一个做的最好的来学。

 前面的文章也介绍了,目前存在的几个开源框架: • 手机淘宝基于 Xposed 进行了改进,产生了针对 Android Dalvik 虚拟机运行时的 Java Method Hook 技术-Dexposed。

 但这个方案犹豫底层 Dalvik 结构过于依赖,最终无法兼容 Android 5.0 以后的ART 虚拟机。

 • 支付宝提出了新的方案 Andfix,它同样是一种底层结构替换的方案,也达到了运行时生效即时修复的效果,而且做到了 Dalvik 和 ART 全版本的兼容。然而它也 是由局限性的,且不说其底层固定结构的替换方案稳定性不好,其使用范文也存在着诸多限制,虽然可以通过代码改造来绕过限制达到同样的 修复目的,但是这种方式即不优雅也不方便。而且更大的问题是 Andfix 只提供了代码层面的修复,对于资源和 so 的修复都还未实现。

 • 其他的就是微信 Tinker、饿了么的 Amigo、美团的 Robust,不过他们都各自有各自的局限性,或者不够稳定、或者补丁过大、或者效率低下 ,或者使用起来太繁琐,大部分技术上看起来似乎可行,但是实际体验并不好。

 我们学习的就是阿里巴巴的新一代非侵入式 Android 热修复方案-Sophix。

 它各个方面都比较优秀,使用也比较方便,唯一不支持的就是四大组件的修复。这是因为如果修复四大组件,必须在 AndroidManifest 里面预先插入代码组件,并且尽可能声明所有权限,这样就会给 原先的 app 添加很多臃肿的代码,对 app 运行流程的侵入性很强。

 在 Sophix 中,唯一需要的就是初始化和请求补丁两行代码,甚至连入口Application 类我们都不需要做任何修改。

 这样就给了开发者最大的透明度和自由度。我们甚至重新开发了打包工具,使的补丁工具操作图形界面化,这种所见即所得的补丁生成 方式也是阿里热修复独家的,因此,Sophix 的接入成本也是目前市面上所有方案里最低的。

 代码修复 代码修复有两大主要方案: • 阿里系的底层替换方案:底层替换方案限制颇多,但是时效性最好,加载轻快,立即见效。

  底层替换方案是在已经加载了的类中直接替换掉原有的方法,是在原来类的基础上进行修改的。因而无法实现对原有类进行方法和字段的增减,因为这样将破坏原有类的结构。

 一旦补丁类中出现了方法的增加和减少,就会导致这个类以及整个 dex 的方法数的变化,方法数的变化伴随着方法索引的变化,这样在 访问方法时就无法正常的索引到正确的方法了。如果字段发生了增加或减少,和方法变化的情况一样,所有字段的索引都会发生变化。

 而新方法中使用到这些老的示例对象时,访问新增字段就会会产生不可预期的结果。

  这是该类方案的固有限制,而底层替换方案最为人逅病的地方,在于底层替换的不稳定性。因为 Hook 方案,都是直接依赖修改虚拟机方法实体的具体字段。因为 Art 虚拟机和 Dalvik 虚拟机的不同,每个版本的虚拟机都要适配,而且Android 系统是开源的,各个厂商都可以对代码进行改造,如果某个厂商进行了修改,那么这种通用性的替换机制就会出问题。这便是不稳定的根源。

 • 腾讯系的类加载方案:类加载方案时效性差,需要重新冷启动才能见效,但修复范围广、限制少。

 类加载方案的原理是在 app 重新启动后让 classloader 去加载新的类。因为在 app运行到一半的时候,所有需要发生变更的类已经被加载过了,在 Android 上是无法对一个类进行卸载的。如果不重启,原来的类还在虚拟机中,就无法加载新类,因此只有在下次重启的时候, 在还没走到业务逻辑之前抢先加载补丁中的新类,这样后续访问这个类的时候,就会用新类,从而达到热修复的目的。

 为什么 sophix 更好? 既然底层替换方案和类加载方案各有优点,把他们联合起来就是最好的选择。Sophix 就是同时涵盖了这两种方案,可以实现优势互补、完全兼顾的作用,可以灵活的根据实际情况自动切换。

 但是 Sophix 有一个缺点就是,他不是开源的,而且是收费的。但是确实强大。