插件化与热修复

305 阅读1分钟

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 的静态变量,并在每个方法执行之前,对这个变量进行了判断,如果这个变量被赋值了,就调用补丁类中的方法,如果没有被赋值,还是调用旧方法

总结: