热修复技术
热修复技术在兴起时一度很流行,但随后遭到了苹果的封杀,我参与的 Android 项目在用与不用间变得含糊不清。不过就技术本身来说,我觉得还是值得了解的,并且就实际用途上也能起到一定的作用。
热修复的诞生主要是为了解决,1.在生产遇到一个小问题,但又影响业务使用的时候,为了避免重新发版本带来的较大资源开销。2.生产遇到的问题简单但影响很严重,例如一个空指针崩溃,为了快速修复和全面覆盖。
另外,Android Studio 的 Instant Run 机制也推动了热修复技术的发展。
热修复技术可以从 3 个方面展开,
-
资源修复
理论来源就是 Instant Run。简单来说就是生成新的 AssetManager 加载新的资源,用新的 AssetManager 对象来替换原有的,使得加载的就是新的资源了。这整个过程都是通过反射来完成。不过我觉得对资源修复的情况可能不多,更多的是代码修复。 -
代码修复
代码修复才是重点,具体实现可分为 3 种,
- 类加载方式
这个要基于类加载的过程,并且还涉及到 Dex 分包机制。在 ClassLoader 加载 dex 文件时,是有序的,也就是主 dex 包先加载,后续按需求动态加载。所以如果某个类有问题,就可以抢在问题类加载之前加载修复类,这样问题类就不会被加载了。
基于这个原理,需要重新加载才能生效,也就是要重启应用。这种方式的热修复技术实现可以看 Tinker。 - Instant Run
在第一次构建 apk 时 Instant Run 会通过 ASM 为每个类植入一段代码,正是这段代码起到了差异对比,也才有了速度的提高。通过,运用这段代码逻辑就可以做到问题类的修复。这种方式的热修复技术实现可以看 Robust。 - 底层替换方式
这个不像「类加载方式」,它从更底层的 Native 层,从数据源头修改数据引用指向从而达到问题的修复。具体是替换 ArtMethod 数据结构的部分或全部字段来实现。
基于这个原理,对设备厂商的标准和版本要求比较高,因为底层更趋于具体化,各个设备的底层差异会更多,所以兼容性要重点考虑。这种方式的热修复技术实现可以看 AndFix。
-
动态链接库修复(so 库修复)
这方面的修复原理和代码修复中的「类加载方式」有些类似,也是利用加载过程抢先加载新的库来修复问题库。
so 库的加载主要涉及 System 的 load 和 loadLibrary 方法,前者加载方式是指定路径,后者是默认 apk 内部路径按名称加载。但底层的实现都是通过 nativeLoad 来实现的。所以修复 so 库就可以用 load 方法加载新的 so 库来修复问题。
以上就是热修复技术的主要内容概括,虽说热修复功能很强大,不过我们应该合理运用,或者说只有在万不得已的时候才使用它,平时项目里还是要保证好产品的质量。
网友评论