网站建设是哪个专业,千图网免费设计图片素材网,网站开发要花费多少钱,推广工具Android 热修复
本文链接#xff1a;https://blog.csdn.net/feather_wch/article/details/132052856 文章目录 Android 热修复方案对比AndFixDeprecateRobust-即时生效Tinker-非及时生效 ClassLoader实战一手动打补丁包 热修复二 方案对比
AndFixDeprecate
1、AndFix为什么…Android 热修复
本文链接https://blog.csdn.net/feather_wch/article/details/132052856 文章目录 Android 热修复方案对比AndFixDeprecateRobust-即时生效Tinker-非及时生效 ClassLoader实战一手动打补丁包 热修复二 方案对比
AndFixDeprecate
1、AndFix为什么可以实时生效 在native层动态替换掉Java层的方法通过native层hook java层代码。 2、如何拿到补丁包的有注解Method
补丁包包含Test.class类加载Test.class反射Method拿到注解(标记了要替换谁)找到目标类
3、如何完成两个对象的替换bug method fix method
Java层伪代码
BugMethod.clazz FixMethod.clazzNative层代码
replace(env, jobject bug, jobject fix)
{// 把bug method的所有属性都替换为补丁method的所有属性
}4、后续拿到的都是修复后的Method.class类对象
Robust-即时生效
美团方案抖音还在用纯Java实现
对每个函数插入一段代码字节码插桩技术。编译阶段在class字节码写代码插入开关: 如果没有补丁包就返回原先逻辑。有补丁包交给补丁。
class State{public static ChangeQuickRedirect changeQuickRedirect;public long getIndex{if(changeQuickRedirect ! null){return PatchProxy.accessDispatch(xxxx);}return 100;}
}拿到补丁包内的类对State.changeQuickRedirect进行赋值
ClassStatePatch clz StatePatch.class; // 拿到补丁包的类
State.changeQuickRedirect clz.newInstance(); // 赋值影响开关的条件判断相关类PatchesInfoImpl.java、StatePatch.java
Tinker-非及时生效
1、关键词DexDiff、增量更新 2、工具 bsdiff 将两者区别信息放到patch上 bsdiff 1.txt 2.txt patch bspatch合成 1.txt patch 2.txt 3、Tinker是差分包 Bug Dex 修复后Dex 4、热修复思路 将补丁Dex放到数组前面 5、什么时候热修复越早越好防止类更早加载就失效了 6、补丁Dex什么时候删除不能删。 7、Application有Bug怎么办不能有Bug
ClassLoader
1、实现类BootClassLoader、PathClassLoader、DexClassLoader、InMemoryClassLoader
2、下面类的ClassLoader是什么
MainActivity.class.getClassLoader() // Path 我们
AppCompatActivity.class.getClassLoader() // Path 第三方
Application.class.getClassLoader() // Boot 系统
getClassLoader() // Path 应用3、PathClassLoader原理
parent BootClassLoader
public class PathClassLoader extends BaseDexClassLoader {public PathClassLoader(String dexPath, ClassLoader parent) {}public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {}
}loadClass做了什么双亲委派先交给BootClassLoader去加载。findClass源码
// BaseDexClassLoader.javaDexPathList pathList; // 内部有一个dexElements数组存储着该ClassLoader的所有dex/resources的路径public BaseDexClassLoader(ByteBuffer[] dexFiles, ClassLoader parent) {super(parent);this.pathList new DexPathList(this, dexFiles);// DexPathList}protected Class? findClass(String name) throws ClassNotFoundException {Class c pathList.findClass(name, suppressedExceptions); // DexPathList中查找if (c null) {ClassNotFoundException cnfe new ClassNotFoundException(Didnt find class \ name \ on path: pathList);throw cnfe;}return c;}
// DexPathList.javapublic Class? findClass(String name, ListThrowable suppressed) {for (Element element : dexElements) {// Element内部的DexFile中查找Class? clazz element.findClass(name, definingContext, suppressed);if (clazz ! null) {return clazz;}}return null;}
// ElementDexPathList的静态内部类private Element[] dexElements;static class Element {private final File path;private final DexFile dexFile;// DexFilepublic Class? findClass(String name, ClassLoader definingContext,ListThrowable suppressed) {return dexFile ! null ? dexFile.loadClassBinaryName(name, definingContext, suppressed): null;}}实战一
手动打补丁包
1、手动补丁包流程
bug修复编译项目生成类的class文件make project生成补丁包
dx --dex --outputpatch.jar com/zte/tv5gshow/test/Bug.class2、补丁包放入到DexFile数组
获取PathClassLoader对象反射到DexPathList对象反射到Element数组oldElement把补丁包编程Element数组patchElement反射执行makePathElement()合并oldElement patchElement newElement Array.newInstance反射吧oldElement数组设置为newElement数组 makePathElement()需要List File集合
File file new File(/sdcard/patch.jar)
list.add(file);
// 作为List的参数传入热修复二
1、PathClassLoader是哪里创建的 ActivityThread中创建了PathClassLoader并且传入了Apk的dex路径 LoadedApk-ApplicaitonLoaders.getDefault().getClassLoader() - ClassLoaderFactory.createClassLoader - new PathClassLoader(dexPath, librarySearchPath, parent) 2、so修复 DexPathList内部属性nativeLibraryPathElements
3、资源修复 和换肤一样