前言
本文是基于《深入探索Android热修复技术原理》一书,所做的归纳总结;本篇是基于热修复一些简单原理非常感谢阿里团队的技术分享,让我们开始吧!
Q1. 什么是热修复?
我们都知道项目出现BUG,修复完成之后需要重新打包发布新版本,并让用户下载更新才能修复应用。这套操作用户体验很差,非常差。so,技术大佬们就把热修复给整了出来,对此我只能说,tql!
图1 热修复流程热修复的优势:
- 无需发布新版本,实时高效
- 无感知修复,无需下载应用,用户体验好
- 修复成功率高
Q2. 能修复些什么?
- 代码修复
- 资源修复
- so库修复
part 1. 代码修复
代码修复主要有两种方案:底层替换方案和类加载方案
两种方案的优劣势:
- 底层替换方案限制多,但是时效性好,加载轻快,立即见效
- 类加载方案时效性差,需要冷启动才能修复,但是修复范围广,限制少
底层替换方案:
- 在已经加载的类中替换掉原来的方法,基于原有的类修改。
- 既然是基于原有的类,这个方案无法对类中方法和字段进行增减,因为这样会破坏类的结构。
如果补丁中的类出现方法增加或者减少,会导致这个类以及整个Dex中方法数发生变化,方法索引也会随之改变,就无法根据索引找到正确的方法了;而类中字段出现增减也是相同的情况,字段索引会产生混乱,在访问新增字段时会产生不可预期的效果。
Sophix:传统底层替换方案是从虚拟机底层修改字段实现的,各个手机厂商之间系统底层可能会产生差异,产生兼容问题。Sophix忽略了底层的ArtMethod的差异,克服了这一限制。
类加载方案:
- 应用重新启动时,让ClassLoader去加载新的类。
- 因为在应用运行到中途,所需要加载的新类在虚拟机中已经被加载过了。旧的对象还在虚拟机中,是无法加载新类的。所以,需要应用重新启动,还没走到业务逻辑之前并抢先加载新类。
dex级别的类插桩方案:重新排列旧包和补丁包中的dex文件的顺序,进行重组,使系统自然识别这个顺序,实现类的覆盖。
part 2. 资源修复
大部分热修复框架的资源修复都或多或少参考了Instant Run。
Instant Run :是android studio2.0新增的一个运行机制,在你编码开发、测试或debug的时候,它都能显著减少你对当前应用的构建和部署的时间。
特点:
- 只对代码改变部分做构建和部署
- 不重新安装应用
- 不重启应用
- 不重启activity
所以我们平时运行项目时第一次编译会特别慢,之后稍有改动,再次运行就快很多了。
原理:
- 构造一个新的AssetManager
- 通过反射调用addAssetPath把完整的新资源包加到AssetManager。这样就得到了一个含有完整新资源的AssetManager。
- 找到之前所有引用AssetManager的地方,并通过反射,把引用处换成新的AssetManager。
Sophix的方案:直接替换现有的AssetManager所引用的资源包,这样就不需要重新创建一个AssetManager了。补丁包的package的id是
0x66
,与原来的资源包id(0x7f
)不会发生冲突。特点:
- 不修改AssetManager的引用处,替换更加完整,安全。
- 不必下载完整包,补丁包中只含变动的资源。
- 不需要在运行时合成完整的包,不占用运行时计算和内存。
part 3. so库修复
so库的修复本质上是对native方法的修复和替换。
采用类修复,通过反射注入的方式,将补丁so库的路径插入到NativeLibraryDirectory数组的最前面。这样在加载so库时,就能加载到补丁so库了,从而达到修复的目的。
网友评论