Android热修复系列(一):认识篇

前言

本文是基于《深入探索Android热修复技术原理》一书,所做的归纳总结;本篇是基于热修复一些简单原理非常感谢阿里团队的技术分享,让我们开始吧!

Q1. 什么是热修复?

我们都知道项目出现BUG,修复完成之后需要重新打包发布新版本,并让用户下载更新才能修复应用。这套操作用户体验很差,非常差。so,技术大佬们就把热修复给整了出来,对此我只能说,tql!

图1 热修复流程

热修复的优势:

  • 无需发布新版本,实时高效
  • 无感知修复,无需下载应用,用户体验好
  • 修复成功率高
图2 热修复各维度比较
Q2. 能修复些什么?
  • 代码修复
  • 资源修复
  • so库修复

part 1. 代码修复

代码修复主要有两种方案:底层替换方案和类加载方案

两种方案的优劣势:

  • 底层替换方案限制多,但是时效性好,加载轻快,立即见效
  • 类加载方案时效性差,需要冷启动才能修复,但是修复范围广,限制少
底层替换方案:
  • 已经加载的类中替换掉原来的方法,基于原有的类修改。
  • 既然是基于原有的类,这个方案无法对类中方法和字段进行增减,因为这样会破坏类的结构。

如果补丁中的类出现方法增加或者减少,会导致这个类以及整个Dex中方法数发生变化,方法索引也会随之改变,就无法根据索引找到正确的方法了;而类中字段出现增减也是相同的情况,字段索引会产生混乱,在访问新增字段时会产生不可预期的效果。

Sophix:传统底层替换方案是从虚拟机底层修改字段实现的,各个手机厂商之间系统底层可能会产生差异,产生兼容问题。Sophix忽略了底层的ArtMethod的差异,克服了这一限制。

类加载方案:
  • 应用重新启动时,让ClassLoader去加载新的类。
  • 因为在应用运行到中途,所需要加载的新类在虚拟机中已经被加载过了。旧的对象还在虚拟机中,是无法加载新类的。所以,需要应用重新启动,还没走到业务逻辑之前并抢先加载新类。

dex级别的类插桩方案:重新排列旧包和补丁包中的dex文件的顺序,进行重组,使系统自然识别这个顺序,实现类的覆盖。

part 2. 资源修复

大部分热修复框架的资源修复都或多或少参考了Instant Run

Instant Run :是android studio2.0新增的一个运行机制,在你编码开发、测试或debug的时候,它都能显著减少你对当前应用的构建和部署的时间。

特点:

  • 只对代码改变部分做构建和部署
  • 不重新安装应用
  • 不重启应用
  • 不重启activity

所以我们平时运行项目时第一次编译会特别慢,之后稍有改动,再次运行就快很多了。

原理:

  1. 构造一个新的AssetManager
  2. 通过反射调用addAssetPath把完整的新资源包加到AssetManager。这样就得到了一个含有完整新资源的AssetManager。
  3. 找到之前所有引用AssetManager的地方,并通过反射,把引用处换成新的AssetManager。

Sophix的方案:直接替换现有的AssetManager所引用的资源包,这样就不需要重新创建一个AssetManager了。补丁包的package的id是0x66,与原来的资源包id(0x7f)不会发生冲突。

特点:

  1. 不修改AssetManager的引用处,替换更加完整,安全。
  2. 不必下载完整包,补丁包中只含变动的资源。
  3. 不需要在运行时合成完整的包,不占用运行时计算和内存。

part 3. so库修复
so库的修复本质上是对native方法的修复和替换。

采用类修复,通过反射注入的方式,将补丁so库的路径插入到NativeLibraryDirectory数组的最前面。这样在加载so库时,就能加载到补丁so库了,从而达到修复的目的。

你可能感兴趣的:(Android热修复系列(一):认识篇)