Android热修复原理

基本概念

热修复是针对apk而言的,所以先来看看apk里都有些什么东西
Android热修复原理_第1张图片

  • assets:保留工程中的assets目录,这些文件是原始文件,包含其他jar里的assets文件
  • lib:so文件
  • META-INF:签名相关文件
  • resources.arsc:资源文件索引,包含了所有文件的索引,以及他们具体的ID值和类型信息,实际资源还在res里
  • res:工程的资源文件,以主工程为主,其他文件(jar包)会合并到该目录下
  • classes.dex文件: 虚拟机执行的文件
  • AndroidManifest文件: 用来做组件查找,只是这里都是二进制格式,并且合并了所有子项目的AndroidManifest文件

首先,AndroidManifest文件出现BUG是无法修复的,它是系统进行解析的的,解析过程中不会访问补丁包信息,因此四大组件,通常也是无法直接添加的,除非预先埋下代理组件,以后添加组件时,使用hook技术偷梁换柱。
下面看代码的修复,由于Java代码最终都编译为classes.dex格式文件,因此要想修改代码逻辑,需要用一个新的dex,在程序运行的时候,加载这个dex文件。
so文件的修复,Android中,所有so文件都是由System.load进行加载,因此在加载的时候设法优先加载补丁包的so文件就能进行完整的替换。

热修复原理

下面基于Qzone的热修复方案讨论热修复原理,Qzone基于dex分包方案,把BUG修复代码放到一个单独的dex补丁文件,让程序运行期间加载dex补丁。
因为Android中所有我们运行期间需要的类都是由ClassLoader(类加载器)进行加载,所以让ClassLoader加载全新的类替换掉出现BUG的类即可完成热修复。特点是重启生效。
Android热修复原理_第2张图片

CLASS_ISPREVERIFIED标记

CLASS_ISPREVERIFIED标志
如果MainActivity类中只引用了Utils类,MainActivity与Utitls都在class.dex中,则加载时MainActivity类被标记为CLASS_ISPREVERIFIED。
如果使用补丁包中的Utils类取代出现bug的Utils,则会导致MainActivity与其引用的Utils不在同一个Dex,但MainActivity已经被打上了CLASS_ISPREVERIFIED标记,这时就会出现冲突,导致校验失败。

AntilazyLoad类会被打包成单独的hack_dex,这样当安装apk的时候,classes.dex内的类都会引用一个在不相同dex中的AntilazyLoad类,防止了类被打上CLASS_ISPREVERIFIED标记,只要没被打上这个标志的类都可以进行打补丁操作。
Android热修复原理_第3张图片

插桩的优缺点

优点:

  • 不需要考虑对dalvik虚拟机和art虚拟机做适配
  • 代码是非侵入式的,对apk体积影响不大

缺点:

  • 需要下次启动才会生效
  • 最大挑战在于性能,即Dalvik平台存在插桩导致的性能损耗,Art平台由于地址偏移问题导致补丁包可能过大的问题
  • 虚拟机在安装期间为类打上CLASS_ISPREVERIFIED标志是为了提高性能的,我们强制防止类被打上标志会影响性能.不过在大项目中拆分dex的问题已经比较严重,很多类都没有被打上这个标志。

你可能感兴趣的:(Android)