AndFix、tinker实现原理简单笔记

AndFix实现原理

特点:
native 底层替换
不需要重启app即可实现bug修复,适用于紧急比较小的bug
稳定性较差,会受到国内ROM厂商对ArtMethod结构更改的影响,
实现步骤:
1.在要修改的方法上添加注解并生成补丁包(.apatch)
2.获取补丁包中的补丁类并遍历其中的方法获取待注解的方法
3.使用补丁中的方法替换bug中的方法
重点类:
1.DexFile dexFile = DexFile.loadDex(...)//加载补丁到缓存目录
2.dexFile.entries();//得到补丁中的类名集合并遍历
3.dexFile.loadClass(...);//通过类名得到Class对象并修复
4.由于android4.4以下是dalvik虚拟机 5.0以上是art虚拟机
Build.VERSION.SDK_INT <=18时 replaceDalvik(...)
else replaceArt(...)
5.每一个java类在虚拟机中都存在一个方法表对应着类中的每个方法,且是一个结构体,里面存着方法入口和字节码地址等
使用哪个方法时就把这个方法压栈。所以首先要找到要替换的方法在虚拟中的结构体,
5.0以上 直接反射获得新旧方法的结构体,将新方法的一些参数赋值给旧方法。
5.0以下通过多了dlopen(libdvm.so,...)dlsym(...) hook旧的方法,将新方法的一些参数赋值给旧方法。

Tinker实现原理

类加载替换
tinker java层热修复原理

1.涉及到两个类:PathClassLoader、DexClassLoader
PathClassLoader是android默认的类加载器,只能加载android系统的apk(/data/app目录下,解压为 dex 后优化为 odex)。
DexClassLoader可以加载路径下的 dex/jar/apk/zip 文件,比 PathClassLoader 更灵活,是实现热修复的关键。
2.他们的父类BaseDexClassLoader有一个成员变量DexPathList,它的属性中有一个 dex 数组,我们只要将替换的类添加到 dexElements 前面即可,
这样类加载器跟据双亲委托模型(Parent Delegation Model)的机制就会使用先找到的类。(ClassLoader 加载类时,先查看自身是否已经加载过该类,
如果没有加载过会首先让父加载器去加载,如果父加载器无法加载该类时才会调用自身的 findClass 方法加载,该逻辑避免了类的重复加载。
所以我们所要实现的就是把要替换的类可见性提前,这样类加载器就会优先找到修复过的类。)

    final class DexPathList {
        private static final String DEX_SUFFIX = ".dex";
        private static final String zipSeparator = "!/";
        private final ClassLoader definingContext;
        private Element[] dexElements;
        private final NativeLibraryElement[] nativeLibraryPathElements;
        private final List nativeLibraryDirectories;
        .....

3.实现步骤:
1.通过反射获取PathClassLoader中的DexPathList中的Element数组(已加载了第一个dex包,由系统加载)
2.通过反射获取DexClassLoader中的DexPathList中的Element数组(将第二个dex包加载进去)
3.将两个Element数组合并之后,再将其赋值给PathClassLoader的Element数组

你可能感兴趣的:(AndFix、tinker实现原理简单笔记)