资源预览内容
第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
第9页 / 共10页
第10页 / 共10页
亲,该文档总共10页全部预览完了,如果喜欢就下载吧!
资源描述
Android 热修复方案分析绝大部分的 APP 项目其实都需要一个动态化方案,来应对线上紧急bug 修复发新版本的高成本.之前有利用加壳,分拆两个dex 结合 DexClassLoader 实现了一套全量更新的热更方案.实现原理在这篇博客中有分解.因为这套方案是在Java端实现 ,并且是全量更新所以兼容性较好,成功率较高 .但是在线上跑了几个月之后就碰到了瓶颈,因为随着业务的增长分拆过之后的dex 文件方法数也超过 65535个,更换拆包方案的话维护成本太高.同时由于没有做差异diff,就带来了 patch 包过大 ,冗余多等缺点 .正好微信的动态化方案Tinker 也开源了,就趁这个机会先把市面上主流的热更方案汇总分析下,再选一个方向深入研究一个尽量兼并兼容性扩展性及时性的方案 .Github 相关数据分析先统计下 github 上几个 star 比较多的开源热更方案,数据为 2016年 11 月 3 号采集的 ,仅供参考.从非技术的角度来分析下表的数据,根据开源时间到最近commit 时间、commit 数量、issues的关闭率和 Release 版本数都可以看出这几个项目目前的维护情况.还有 Wiki 相关文档的支持.怎么看 Tinker 现在都是一副很生猛的架势.而阿里百川的商业化Hotfix 现在还在公测 ,方式用的是 Andfix ,把热更做成一个商业化的功能,就不清楚Andfix以后在 github 上的维护情况了 ,但是同时也证明了 Andfix的价值 .而 Dexposed 一直没有兼容 ART, 这里就先不详细分析了.实现原理AndfixAndfix 实现热更的核心方法是在而替换的方法则是由源apkJNI 中动态文件和修改过的hook 替换目标方法 ,来达到即时修复bug 的目的 .apk 文件的dex 做 diff, 反编译补丁包工具apkpatch 可以看到两个dex遍历做diff的过程.public DiffInfo diff(File newFile, File oldFile) throws IOException DexBackedDexFile newDexFile = DexFileFactory.loadDexFile(newFile, 19, true);DexBackedDexFile oldDexFile = DexFileFactory.loadDexFile(oldFile, 19, true);DiffInfo info = DiffInfo.getInstance();boolean contains = false;for(Iterator iterator = newDexFile.getClasses().iterator(); iterator.hasNext();)DexBackedClassDef newClazz = (DexBackedClassDef)iterator.next();Set oldclasses = oldDexFile.getClasses();for(Iterator iterator1 = oldclasses.iterator(); iterator1.hasNext();)DexBackedClassDef oldClazz = (DexBackedClassDef)iterator1.next(); if(newClazz.equals(oldClazz)compareField(newClazz, oldClazz, info);compareMethod(newClazz, oldClazz, info);contains = true;break;if(!contains)info.addAddedClasses(newClazz);return info;遍历出修改过的方法加上一个MethodReplace 的注解 (包含要替换的目标类和目标方法),生成一个 diffdex,再签上名更名为.apatch 的补丁包通过更新的方式分发的各个终端处.通过反编译中间 diff dex 可以看到补丁文件中对fix method 的描述 .public static String getBuildId() return 6f3d1afc-d890-47c2-8ebe-76dc6c53050c;终端在效验过补丁包的合法性后据注解中的目标方法配置,将method.,则把补丁包中带有MethodReplaceold method 利用 classloader 加载进内存注解的方法遍历出来,然后交给 JNI 去替换,根oldprivate void fixClass(Class clazz, ClassLoader classLoader) Method methods = clazz.getDeclaredMethods(); MethodReplace methodReplace;String clz;String meth;for (Method method : methods) methodReplace = method.getAnnotation(MethodReplace.class);if (methodReplace = null)continue;clz = methodReplace.clazz();meth = methodReplace.method();if (!isEmpty(clz) & !isEmpty(meth) replaceMethod(classLoader, clz, meth, method);private void replaceMethod(ClassLoader classLoader, String clz, String meth, Method method) try String key = clz + + classLoader.toString();Class clazz = mFixedClass.get(key);if (clazz = null) / class not loadClass clzz = classLoader.loadClass(clz);/ initialize target classclazz = AndFix.initTargetClass(clzz);if (clazz != null) / initialize class OKmFixedClass.put(key, clazz);Method src = clazz.getDeclaredMethod(meth,method.getParameterTypes();AndFix.addReplaceMethod(src, method); catch (Exception e) Log.e(TAG , replaceMethod, e);在 Andfix.app 中可以看到 JNI 中 replaceMethod 方法 ,由于从 Lolipop 开始 Android 放弃使用dalvik 转向 android runtime, 所以 Andfix 也要区分不同的平台进行替换 .像 Dexposed 到目前为止都没有做 ART 的兼容 .static void replaceMethod(JNIEnv* env, jclass clazz, jobject src, jobject dest) if (isArt) art_replaceMethod(env, src, dest); else dalvik_replaceMethod(env, src, dest);extern void _attribute_ (visibility (hidden) dalvik_replaceMethod( JNIEnv* env, jobject src, jobject dest) jobject clazz = env-CallObjectMethod(dest, jClassMethod); ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef_fnPtr(dvmThreadSelf_fnPtr(), clazz);clz-status = CLASS_INITIALIZED;Method* meth = (Method*) env-FromReflectedMethod(src); Method* target = (Method*) env-FromReflectedMethod(dest);LOGD(dalvikMethod: %s, meth-name);meth-accessFlags |= ACC_PUBLIC;meth-methodIndex = target-methodIndex;meth-jniArgInfo = target-jniArgInfo;meth-registersSize = target-registersSize;meth-outsSize = target-outsSize;meth-insSize = target-insSize;meth-prototype = target-prototype;meth-insns = target-insns;meth-nativeFunc = target-nativeFunc;由于兼容问题在ART 的 replaceMethod 方法中对每一个不同的系统版本进行区分extern void _attribute_ (visibility (hidden) art_replaceMethod( JNIEnv
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号