本文框架

  • 什么是热修复?
  • 热修复框架分类
  • 技术原理及特点
  • Tinker框架解析
  • 各框架对比图
  • 总结

  通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单描述一下Tinker的框架结构。

一、什么是热修复?

正常开发流程

热修复开发流程

热修复优势

修复什么?

二、热修复框架分类

现状:百花齐放百家争鸣

简单分类

更合理的分类

三、技术原理及特点

3.1 阿里Dexposed -- native解决方案

原理:

  • 直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能

  他的思想完全来源于Xposed框架,完美诠释了AOP编程,这里用到最核心的知识点就是在native层获取到指定方法的结构体,然后改变他的nativeFunc字段值,而这个值就是可以指定这个方法对应的native函数指针,所以先从Java层跳到native层,改变指定方法的nativeFunc值,然后在改变之后的函数中调用Java层的回调即可。实现了方法的拦截功能。

  • 基于开源框架Xposed实现,是一种AOP解决方案
  • 只Hook App本身的进程,不需要Root权限

优点:

  • 即时生效
  • 不需要任何编译器的插桩或者代码改写,对正常运行不引入任何性能开销。这是AspectJ之类的框架没法比拟的优势;
  • 对所改写方法的性能开销也极低(微秒级),基本可以忽略不计;
  • 从工程的角度来看,热补丁仅仅是牛刀小试,它真正的威力在于『线上调试』;
  • 基于Xposed原理实现的AOP不仅可以hook自己的代码,还可以hook同进程的Android SDK代码,这也就可以让我们有能力在App中填上Google自己挖的坑。

缺点:

  • Dalvik上近乎完美,不支持ART(需要另外的实现方式),所以5.0以上不能用了;
  • 最大挑战在于稳定性与兼容性,而且native异常排查难度更高;
  • 由于无法增加变量与类等限制,无法做到功能发布级别;

相关链接:

3.2 阿里AndFix -- native解决方案

原理:

  • 与Dexposed一样都基于开源框架Xposed实现,是一种AOP解决方案

优点:

  • 即时生效
  • 支持dalvik和art(AndFix supports Android version from 2.3 to 7.0, both ARM and X86 architecture, both Dalvik and ART runtime, both 32bit and 64bit.)
  • 与Dexposed框架相比AndFix框架更加轻便好用,在进行热修复的过程中更加方便了

缺点:

  • 面临稳定性与兼容性问题
  • AndFix不支持新增方法,新增类,新增field等

AndFix(Dexpsed)框架不稳定的原因(痛点)

相关链接:

3.3 QQ空间--Dex插桩方案(大众点评的Nuwa参考其实现并开源)

原理:

  • 原理是Hook了ClassLoader.pathList.dexElements[]。因为ClassLoader的findClass是通过遍历dexElements[]中的dex来寻找类的。当然为了支持4.x的机型,需要打包的时候进行插桩。
  • 越靠前的Dex优先被系统使用,基于类级别的修复

优点:

  • 不需要考虑对dalvik虚拟机和art虚拟机做适配
  • 代码是非侵入式的,对apk体积影响不大

缺点:

  • 需要下次启动才会生效
  • 最大挑战在于性能,即Dalvik平台存在插桩导致的性能损耗,Art平台由于地址偏移问题导致补丁包可能过大的问题
  • 虚拟机在安装期间为类打上CLASS_ISPREVERIFIED标志是为了提高性能的,我们强制防止类被打上标志是否会影响性能?这里我们会做一下更加详细的性能测试.但是在大项目中拆分dex的问题已经比较严重,很多类都没有被打上这个标志。

插桩方案性能上的痛点:

相关链接:

3.4 美团Robust -- Instant Run 热插拔原理

原理:

  • Robust插件对每个产品代码的每个函数都在编译打包阶段自动的插入了一段代码,插入过程对业务开发是完全透明
  • 编译打包阶段自动为每个class都增加了一个类型为ChangeQuickRedirect的静态成员,而在每个方法前都插入了使用changeQuickRedirect相关的逻辑,当 changeQuickRedirect不为null时,可能会执行到accessDispatch从而替换掉之前老的逻辑,达到fix的目的。

优点:

  • 几乎不会影响性能(方法调用,冷启动)
  • 支持Android2.3-8.x版本
  • 高兼容性(Robust只是在正常的使用DexClassLoader)、高稳定性,修复成功率高达99.9%
  • 补丁实时生效,不需要重新启动
  • 支持方法级别的修复,包括静态方法
  • 支持增加方法和类
  • 支持ProGuard的混淆、内联、优化等操作

缺点:

  • 代码是侵入式的,会在原有的类中加入相关代码
  • so和资源的替换暂时不支持
  • 会增大apk的体积,平均一个函数会比原来增加17.47个字节,10万个函数会增加1.67M。
  • 会增加少量方法数,使用了Robust插件后,原来能被ProGuard内联的函数不能被内联了

相关链接:

3.5 微信Tinker

原理:

  • 服务端做dex差量,将差量包下发到客户端,在ART模式的机型上本地跟原apk中的classes.dex做merge,merge成为一个新的merge.dex后将merge.dex插入pathClassLoader的dexElement,原理类同Q-Zone,为了实现差量包的最小化,Tinker自研了DexDiff/DexMerge算法。Tinker还支持资源和So包的更新,So补丁包使用BsDiff来生成,资源补丁包直接使用文件md5对比来生成,针对资源比较大的(默认大于100KB属于大文件)会使用BsDiff来对文件生成差量补丁。


优点:

  • 支持动态下发代码
  • 支持替换So库以及资源

缺点:

  • 不能即时生效,需要下次启动

Tinker已知问题:

  • Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件(1.9.0支持新增非export的Activity);
  • 由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码;
  • 在Android N上,补丁对应用启动时间有轻微的影响;
  • 不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed";
  • 对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。

Tinker性能痛点:

  • Dex合并内存消耗在vm head上,容易OOM,最后导致合并失败。
  • 如果本身app占用内存已经比较高,可能容易导致app本系统杀掉。

相关链接:

3.6 阿里Sophix

原理(双剑合璧):

优化Andfix(突破底层结构差异,解决稳定性问题):


Andfix底层ArtMethod结构时采用内部变量一一替换,倒是这个各个厂商是会修改的,所以兼容性不好。

Sophix改变了一下思路,采用整体替换方法结构,忽略底层实现,从而解决兼容稳定性问题。

突破QQ和Tinker的缺陷


QQ和Tinker的缺陷

Sophix对dex的解决方案

  • Dalvik下采用阿里自研的全量dex方案:不是考虑把补丁包的dex插到所有dex前面(dex插桩),而是想办法在原理的dex中删除(只是删除了类的定义)补丁dex中存在的类,这样让系统查找类的时候在原来的dex中找不到,那么只有补丁中的dex加载到系统中,系统自然就会从补丁包中找到对应的类。
  • Art下本质上虚拟机以及支持多dex的加载,Sophix的做法仅仅是把补丁dex作为主dex(classes.dex)而已,相当于重新组织了所有的dex文件:把补丁包的dex改名为classes.dex,以前apk的所有dex依次改为classes2.dex、classes3.dex ... classesx.dex,如下图所示。

资源修复另辟蹊径


常用方案(Instant Run技术):这种方案的兼容问题在于替换AssetManager的地方

Sophix资源修复方案

SO修复另辟蹊径


四、Tinker框架解析

  之所以只贴了Tinker的代码框架,是因为目前开源的方案中是最好的,当然除了Robust。

代码结构

修复流程

这里后续再补一个详细的源码分析,敬请期待

五、对比图(来自不同的地方)

来自Tinker的对比

来自Sophix的对比

来自蘑菇街 Android 热修复探索之路

其他文章

浅谈Android热修复:

六、总结

  如果不考虑增大apk的体积,只是简单的修复代码,不修复so和资源,选择Robust是最稳定的,否则的话选择Tinker是一个不错的方案。虽然阿里Sophix横空出世,但是它不开源,而且商业收费,所以一般不是很赚钱的app选择收费的可能就很小了。不过它确实各方面都做了大量的优化,本文中的很多知识点也来源于阿里的《Android热修复技术原理.pdf》一书,本书值得一读,里面就是基于Sophix框架来编排的。

Android热修复技术原理详解(最新最全版本)的更多相关文章

  1. Android热修复技术原理详解

    阿里Dexposed -- native解决方案 原理: 直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能   他的思想完全来源于Xposed框架,完美诠释 ...

  2. 深入探索Android热修复技术原理读书笔记 —— 代码热修复技术

    在前一篇文章 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍中,对热修复技术进行了介绍,下面将详细介绍其中的代码修复技术. 1 底层热替换原理 在各种 Android 热修复方案中 ...

  3. 深入探索Android热修复技术原理读书笔记 —— so库热修复技术

    热修复系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 深入探索Android热修复技术原理读书笔记 ...

  4. 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍

    1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...

  5. 深入探索Android热修复技术原理读书笔记 —— 资源热修复技术

    该系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 1 普遍的实现方式 Android资源的热修复,就 ...

  6. 全面了解Android热修复技术

    WeTest 导读 本文探讨了Android热修复技术的发展脉络,现状及其未来. 热修复技术概述 热修复技术在近年来飞速发展,尤其是在InstantRun方案推出之后,各种热修复技术竞相涌现.国内大部 ...

  7. Android 热修复技术(1)---原理

    热修复技术分为几部分: 原理介绍 Android HotFix源码分析 自定义框架 1.Android分包MultiDex原理 首先Dex是什么东西? Dex就是Window里面的exe文件 也就是可 ...

  8. Android热修复技术选型(不在市场发布新版本的情况下,直接更新app)

    2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们在原理各有不同,适用场景各异,到 ...

  9. Android热修复技术选型——三大流派解析

    声明,本文转载自微信公众号文章 2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们 ...

随机推荐

  1. SDN第一次作业

    作业链接 你会选择作 网络编程 方向的程序员吗?为什么? 光凭阅读此篇文章我还无法确定以后是否选择作 网络编程 方向的程序员.出于自身知识的匮乏,文章中提到的很多东西都没有概念,全篇一口气阅读下来,给 ...

  2. 理解Java Integer的缓存策略【转】

    本文由 ImportNew - 挖坑的张师傅 翻译自 javapapers.欢迎加入翻译小组.转载请见文末要求. 本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的 ...

  3. Kudu存储实战笔记

    有人会问,为啥要用这个叫啥Kudu的,Kudu是啥? 就像官网所说,Kudu是一个针对Apache hadoop 平台而开发的列式存储管理器,在本菜鸟看来,它是一种介于hdfs与hbase的一种存储. ...

  4. linux集群架构

    Linux集群架构   根据功能划分为两大类:高可用和负载均衡 高可用集群通常为两台服务器,一台工作,另外一台作为冗余,当提供服务的机器宕机,冗余将接替继续提供服务 实现高可用的开源软件有:heart ...

  5. Linux常用命令手册

    Linux常用命令手册 NO 分类 PS1 命令名 用法及参数 功能注解 对应章节 1 文件管理 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件     文件管理 # ls ls ...

  6. 关于ssh登录出现异常警告:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

    提示警告信息如下: arnold@WSN:~$ ssh 10.18.46.111 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...

  7. 基于jq的表单填充

    //表单填充 formDataLoad: function (domId, obj) { for (var property in obj) { if (obj.hasOwnProperty(prop ...

  8. 【学习笔记】Hibernate 注解 (Y2-1-9)

    Hibernate注解 1.什么是注解在类上或者方法上打上其他类型的类型元数据 @标志 使用过的注解: @override  方法重写 @Test Junit 单元测试 @Before 单元测试 @A ...

  9. Hibernate学习(三)一对多数据的保存

    保存习惯代码 @Test public void saveTwoTableTest(){ Transaction transaction = null; try { transaction = ses ...

  10. JavaScript 一个进行枚举选择的jquery插件(仿easyui风格)

    某次做项目要实现一个功能: 按星期选择一个连续的时间范围 比如:周一到周五,周六到周日 或 周六到周三 聪明的朋友马上想出办法:用两个选项为周一到周日的下拉列表实现,对 那样可以,但是我觉得不够友好, ...