Android热修复技术选型——三大流派解析
先找到应用入口`TinkerApplication`,在`onBaseContextAttached()`调用了`loadTinker()`, 进入TinkerLoader的tryLoad()方法中, 从方法名可以预见,在tryLoadPatchFilesInternal()中尝试加载本地的补丁,再经过跳转进入核心修复功能类SystemClassLoaderAdder.class中。 代码中可以看出,根据Android版本的不同,分别采取具体的修复操作,不过原理都是一样的。我们以V19为例, 从代码中可以看到,通过反射操作得到PathClassLoader的DexPatchList,反射调用patchlist的makeDexElements()方法吧本地的dex文件直接替换到Element[]数组中去,达到修复的目的。 对于如何进行patch.dex与classes.dex的合并操作,这里微信开启了一个新的进程,开启新进程的服务TinkerPatchService进行合并。 整体的流程如下: 从流程图来看,同样可以很明显的找到这种方式的特点: 优势: 1. 合成整包,不用在构造函数插入代码,防止verify,verify和opt在编译期间就已经完成,不会在运行期间进行。 2. 性能提高。兼容性和稳定性比较高。 3. 开发者透明,不需要对包进行额外处理。 不足: 1. 与超级补丁技术一样,不支持即时生效,必须通过重启应用的方式才能生效。 2. 需要给应用开启新的进程才能进行合并,并且很容易因为内存消耗等原因合并失败。 3. 合并时占用额外磁盘空间,对于多DEX的应用来说,如果修改了多个DEX文件,就需要下发多个patch.dex与对应的classes.dex进行合并操作时这种情况会更严重,因此合并过程的失败率也会更高。 三、阿里百川HotFix 阿里百川推出的热修复HotFix服务,相对于QQ空间超级补丁技术和微信Tinker来说,定位于紧急BUG修复的场景下,能够最及时的修复BUG,下拉补丁立即生效无需等待。 1、AndFix实现原理 AndFix不同于QQ空间超级补丁技术和微信Tinker通过增加或替换整个DEX的方案,提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启,对应用无性能消耗的目的。 原理图如下: 2、AndFix实现过程 对于实现方法的替换,需要在Native层操作,经过三个步骤: 接下来以Dalvik设备为例,来分析具体的实现过程: 1、setup() 对于Dalvik来说,遵循JIT即时编译机制,需要在运行时装载libdvm.so动态库,获取以下内部函数: 1) dvmThreadSelf( ):查询当前的线程; 2)dvmDecodeIndirectRef( ):根据当前线程获得ClassObject对象。 2、setFieldFlag 该操作的目的:把 private、protected的方法和字段都改为public,这样才可被动态库看见并识别,因为动态库会忽略非public属性的字段和方法。 3、replaceMethod 该步骤是方法替换的核心,替换的流程如下: AndFix对ART设备同样支持,具体的过程与Dalvik相似,这里不再赘述。 从技术原理,不难看出阿里百川HotFix的几个特点: 优势: 1. BUG修复的即时性 2. 补丁包同样采用差量技术,生成的PATCH体积小 3. 对应用无侵入,几乎无性能损耗 不足: 1. 不支持新增字段,以及修改<init>方法,也不支持对资源的替换。 2. 由于厂商的自定义ROM,对少数机型暂不支持。 综合分析如下: 热修复技术的坑与解 我们可以看到,QQ空间超级补丁技术和微信Tinker的修复原理都基于类加载,在功能上已经支持类、资源的替换和新增,功能非常强大。既然已经有了这么强大的热修复技术,为什么阿里百川还要推出自己的热修复方案HotFix呢? 一、多DEX带来的性能影响 我们知道,多DEX方案原来是用于解决应用方法数65k的问题,现在google也官方支持了MultiDex的实现方案。超级补丁技术和Tinker却作为一种热修复的方案,平生给应用增加了多个DEX,而多DEX技术最大的问题在于性能上的坑,因此基于这种方案的补丁技术影响应用的性能是无疑的。 1. 启动加载时间过长 我们可以看到,超级补丁技术和Tinker都选择在Application的attachBaseContext()进行补丁dex的加载,即时这是加载dex的最佳时机,但是依然会带来很大的性能问题,首当其冲的就是启动时间太长。 (编辑:武汉站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |