安卓开发热修复技术原理及选型

到我写这篇博文为止,现行的热修复技术主要有四种:美团的Robust、qq空间的Nuwa,微信的Tinker,阿里百川HotFix,但是更确切的说应该是有三种,Tinker和HotFix,因为Tinker是基于Nuwa的,原理一样,是它的进化版,我们到Github(https://github.com/jasonross/Nuwa )上可以看到,它已经一年没有更新了。

安卓开发热修复技术原理及选型_第1张图片

美团的Robust(Github链接、官方文档),虽然最近都在更新,但是还不够完善,无法更新so\res等文件,没有形成系统的使用文档以及补丁包的管理,使用起来非常麻烦,所以在这里我们将分别讨论微信Tinker和阿里百川HotFix的原理及技术选型。

原理

一、Tinker

Tinker(官网链接) 是一个开源项目(Github链接),讲到Tinker的原理我们要先说说Nuwa的原理,Nuwa实现热修复的方案基于Android的dex分包基础上,dex分包是为了解决方法数达到64K天花板问题,简单来说就是将一个dex文件拆分成多个dex文件,在应用启动时其中一个作为主dex进行加载,应用启动后将会逐个加载其他dex,多个dex文件会排列成一个有序的数组,Dalvik虚拟机加载类的过程中,会顺序遍历这些dex文件,在每个dex文件中查找对应得类,如果找到就返回,没有找到就继续在下一个dex文件中查找。因此,理论上,如果多个dex文件中存在相同的类,那么排在数组前面的dex文件中的类将会被优选选择。因此,Numa实现热修复是将修复后的代码所在的dex插入到dex数组的最前面使达到新类替换旧类的目的,读者如果想深入了解可以看看这篇关于安卓加载类的过程的博文:https://juejin.im/entry/57c3a2a3c4c9710061927b6c , 原理如下图所示:

安卓开发热修复技术原理及选型_第2张图片
Nuwa实现原理.png

但是这种方案有一个缺点,由于新增加了dex,如果修复的类到了一定数量就会影响启动性能特备是再ART模式下更容易导致补丁包异常大,针对这个不足,微信提出了Tinker方案,原理如下:

安卓开发热修复技术原理及选型_第3张图片
图片.png
安卓开发热修复技术原理及选型_第4张图片
图片.png
二、阿里百川HoxFix(Sophix)

官网链接
阿里的热修复技术经历了Dexposed --->AndFix --> HoxFix 1.x --> HoxFix2.0.1(Sophix)的演化,
从最初的只支持方法修复到现在可以实现全修复,并且支持所有安卓系统版本,稳定性和兼容性、安全性都得到了大的提升,由于最新的Sophix没有开源,我们只能从它的前身AndFix(Github链接)去大概看看它的实现原理。AndFix只能修复方法,其参考了Hook的思想,跟Dexposed 相比做到了更好的系统兼容性。

安卓开发热修复技术原理及选型_第5张图片
AndFix修复方法的原理.png

对于实现方法的替换,需要在Native层操作,经过三个步骤,实现过程如下图所示:

安卓开发热修复技术原理及选型_第6张图片
图片.png
阿里Hotfix2.X 类修复方案

Hotfix2.X在热修复过程中是不侵入打包过程的,而是通过补丁工具生成补丁。由于热部署Andfix修复正在运行的方法有Crash的风险, 所以补丁工具提供参数由业务方来决定是否尝试走热部署;如果用户Patch的方法没有被高频调用同时又有实时生效的需求,那么可以优先选择走热部署方案;但这并非绝对,当代码变更导致热部署不支持时,还是会转向冷部署。

热部署

热部署不用重启应用就能够看到效果,就是AndFix支持的代码变更,此时走优化后的AndFix方案,也就是Hotfix1.X方案。

冷部署

冷部署需要重启应用才能够看到效果,就是AndFix不支持的代码变更。冷部署针对Davilk和Art分别做了不同的处理。

阿里Hotfix2.X SO文件修复方案

Davilk和ART下SO文件加载的方式不一样,导致了需要区分Art和Davilk做不同的处理:

ART下预Load原来的SO文件,再加载补丁SO文件;

Davilk下预Load补丁SO文件,再加载原来的SO文件。

这里的关键是:综合机型支持的Abis和补丁包中的Abis共同决定补丁SO的新LibPath。这两种加载方式都需要对加载两次SO文件,势必会增加一次本地内存的消耗,因此为了达到更好的性能,在Hotfix2.X中提供了下面两个接口替换掉系统加载SO文件的接口:

SOPatchManager.load(String libPath) 代替     System.load(String pathName)

SOPatchManager.loadLibrary(String libName)代替     System.loadLibrary(String libName)
阿里Hotfix2.X 资源文件修复方案

在资源文件中,资源ID编码于Resources.arsc文件中,排布紧密,并按照排布顺序进行自动编号;RES目录保存所有带ID的资源文件。布局文件为二进制形式的XML文件,XML以资源ID的方式引用其他资源;Assets目录存放所有原始文件,不带ID;Aapt进行资源的构造,包括自动分配资源ID与R文件的生成,默认情况下,每次编译不保证和之前包中的ID一致。

目前市面上普遍采用的三种资源修复方案:

1、差量合成完整的资源包,运行时完整加载资源;这种方案的缺点是:合成资源占用时间和内存,容易引起卡顿。
2、 修改aapt,对以后可能新增的资源提前留空,运行时Patch包中新增资源ID对应留出的位置;该方案的缺点是:需改变打包流程,修改代码并编译替换SDK中的Aapt;打包侵入太强,且留空占用一定磁盘空间。留空多少是预先定好的,无法改变。
3、插件化,组件化资源;这种方式的缺点是:资源需要划分模块,提前规划。

百川资源文件修复方案直接基于新旧两个APK来构造补丁包,不需要改造AAPT,对编译过程无要求;同时,精确比较各个资源ID的使用情况,最大程度利用原先基线包资源,补丁包中只包含新增和修改的资源;在运行时无需合成操作,快速应用生效,不影响性能

两种热修复技术对比(2017年3月29日为止最新)

项目 阿里Sophix 微信Thinker
类替换 yes yes
so替换 yes yes
资源替换 yes yes
全平台支持 yes yes
补丁包大小 较小 较小
即时生效 yes(增删方法采用冷启动) no (重启生效)
性能损耗 较小
侵入式打包 无侵入式打包 依赖侵入式打包
可视化打补丁包 yes no
接入复杂度 简单 相对复杂
安全性 加密传输及签名校验 、采用https请求 未知
应用加固 支持(用未加固的apk打补丁包) 未知
费用 免费 日请求量<1W免费,大于1W按级别收取不同费用

目前官网公布的使用Sophix 的安卓应用,如下图所示:

安卓开发热修复技术原理及选型_第7张图片
图片.png

使用Tinker的应用目前只知道有微信,至于有没有其它产品,由于官方没有公布,暂时不知道。

总结

个人对比:
1、对bug修复及时,大部分bug不需要重新启动就可以立即看到效果;
2、接入的步骤比Tinker简单,降低了学习成本;
3、比Tinker更低的性能损耗;
4、最重要的:免费,以后会不会收费就不知道了;
5、Thinker收费,意味着更好的服务,更稳定的性能;
6、目前截止到Sophix2.0.9版本为止,对res下的文件bug修复易导致崩溃;
基于以上几点,我建议大家选择用Sophix 进行热更新;

你可能感兴趣的:(安卓开发热修复技术原理及选型)