Skip to content

Latest commit

 

History

History
56 lines (23 loc) · 2.59 KB

File metadata and controls

56 lines (23 loc) · 2.59 KB

1.热修复和插件化区别

插件化和热修复的原理,都是动态加载 dex/apk 中的类/资源,让宿主正常的加载和运行插件(补丁)中的内容。 两者的目的不同。

插件化目标是想把需要实现的模块或功能当做一个独立的提取出来,减少宿主的规模。所以插件化重在解决组件的生命周期,以及资源的问题

热修复目标在修复已有的问题。重在解决替换已有的有问题的类/方法/资源等。

2.热修复原理

代码修复主要有三个方案,分别是底层替换方案、类加载方案和Instant Run方案。

类加载方案

Android中要加载某一个类,最终都是调动DexPathList中的findClass()方法

加载一个类的时候,都会去循环dexElements数组取出里面的dex文件,然后从dex文件中找目标类,只要目标类找到,则直接退出循环,也就是后面的dex文件就没有被取到的机会。 那我们就可以根据这样的一个原理,将修改后的类编译后统一放在patch.dex补丁文件中,通过反射将patch.dex放在dexElemets这个数组的第一个元素,这样,当加载出现bug的类时,首先会先从patch.dex这个文件中去找,因为我们将修改后的类放在了patch.dex文件中,所以肯定会被找到(此时加载到的是已经修复的类),一旦被找到,后面dex中的bug类就没办法被加载到。

QZone修复的步骤:

  1. 通过获取到当前应用的Classloader,即为BaseDexClassloader

  2. 通过反射获取到他的DexPathList属性对象pathList

  3. 通过反射调用pathList的dexElements方法把patch.dex转化为Element[]

  4. 两个Element[]进行合并,把patch.dex放到最前面去

  5. 加载Element[],达到修复目的

Tinker修复的流程:

微信的Tinker将新旧APK做了diff,得到path.dex,再将patch.dex与手机中APK的classes.dex做合并,生成新的classes.dex,然后在运行时通过反射将classes.dex放在Elements数组的第一个元素。

底层替换方案

在native层将传入的javaMethod在ART虚拟机中对应一个ArtMethod指针,ArtMethod结构体中包含了Java方法的所有信息,包括执行入口、访问权限、所属类和代码执行地址等。

替换ArtMethod结构体中的字段或者替换整个ArtMethod结构体,这就是底层替换方案。

AndFix采用的是替换ArtMethod结构体中的字段,这样会有兼容性问题,因为厂商可能会修改ArtMethod结构体,导致方法替换失败。

Sophix采用的是替换整个ArtMethod结构体,这样不会存在兼容问题。