android中类加载
public class PathClassLoader extends BaseDexClassLoader {
}
public class BaseDexClassLoader extends ClassLoader {
private final DexPathList pathList;
}
final class DexPathList {
// 保存了 dex 的列表
private Element[] dexElements;
public Class findClass(String name, List<Throwable> suppressed) {
// 遍历 dexElements
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
// 从 DexFile 中查找 Class
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
// ...
return null;
}
}
热修复方案
native hook替换ArtMethod内容
本质就是把旧方法的 ArtMethod 内容替换成新方法的 ArtMethod 内容
兼容性差,由于 Android 系统每个版本的实现都有差别,所以需要做很多的兼容
// 创建补丁的 ClassLoader
pluginClassLoader = DexClassLoader(pluginPath, dexOutPath.absolutePath, nativeLibDir.absolutePath, this::class.java.classLoader)
// 通过补丁 ClassLoader 加载新方法
val toMethod = pluginClassLoader.loadClass("com.zy.hotfix.native_hook.PatchNativeHookUtils").getMethod("getMsg")
// 反射获取到需要修改的旧方法
val fromMethod = nativeHookUtils.javaClass.getMethod("getMsg")
dex插桩
DexPathList 中有 Element[] dexElements//代表dex文件目录 Element[] nativeLibraryPathElements//代表so库文件目录 插桩的原理就是在数组前面插入备选的dex文件或者so文件
Instant Run方案
美团参照其原理实现了 Robust 热修复框架。 原理是,给每个 Class 中新增一个 changeQuickRedirect 的静态变量,并在每个方法执行之前,对这个变量进行了判断,如果这个变量被赋值了,就调用补丁类中的方法,如果没有被赋值,还是调用旧方法