Android热修复框架之优逆势分析(Hotfix)

Android平台出现了一些优秀的热更新方案,主要可以分为4类:

  • 基于Instant Run 热插拔方案:美团的Robust(实时修复)

  Robust插件对每个产品代码的每个函数都在编译打包阶段自动的插入了一段代码,对方法进行了Hook,类似AOP的方式。

  • 基于multidex的热修复方案:代表有Qzone的超级补丁、大众点评的Nuwa、百度金融的RocooFix、 饿了么的Amigo和微信的Tinker(也可以修复so和资源)等(重新冷启动修复)

  需要反射更改DexElements,改变Dex的加载顺序,这使得patch需要在下次启动时才能生效,实时性就受到了影响,同时这种方案在android N [speed-profile]编译模式下可能会有问题。

  • 基于native hook方案:如阿里开源的Andfix和Dexposed(实时修复)

  需要针对dalvik虚拟机和art虚拟机做适配,需要考虑指令集的兼容问题,需要native代码支持,兼容性上会有一定的影响;

  • 基于阿里混合模式:阿里没有开源的Sophix(兼具实时修复和冷启动修复)

  在Andfix的基础上进行优化和改进,所以具有实时修复特点。在Dex的加载,资源加载上都做了优化,解决了其他热修复框架上面无法解决的痛点。整体做了大量的优化和改进,唯一的遗憾就是不开源,但是也将整套技术方案整理成电子书,也算是一种回馈吧。

相关技术文章

阿里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异常排查难度更高;
  • 由于无法增加变量与类等限制,无法做到功能发布级别;

相关链接:

阿里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等

相关链接:

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

原理:

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

优点:

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

缺点:

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

相关链接:

美团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内联的函数不能被内联了

相关链接:

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

相关链接:

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

来自微信

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

其他文章

浅谈Android热修复:

http://blog.csdn.net/caihongdao123/article/details/52051799

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

OpenDaylight铍版本初体验——坑还多吗

OpenDaylight项目发布铍版本(ODL Be),这也是其发布的第四个版本,距离上次发布锂版本(SR3)仅仅只相隔了两个半月,相比较以前版本发布,时间较短...

4098
来自专栏蓝天

Linux下可以替换运行中的程序么?

今天被朋友问及“Linux下可以替换运行中的程序么?”,以前依稀记得Linux下是可以的(而Windows就不让),于是随口答道“OK”。结果朋友发来一个执行结...

1922
来自专栏信安之路

用powershell下载文件的姿势你研究过吗?

PowerShell 的最大优势在于以 .NET 框架为基础。 .NET 框架在脚本领域几乎是无所不能,这是一个优点,也有可能成为一个方便黑客攻击的一个强大的便...

4320
来自专栏程序人生

深入了解IAM和访问控制

本文为InfoQ中文站特供稿件,首发地址为:http://www.infoq.com/cn/articles/aws-iam-dive-in。 访问控制,换句话...

5437
来自专栏腾讯云安全的专栏

你熟悉的Android Root 方式有哪些?|附演示视频

2835
来自专栏java达人

武林外传—阿沅,这是依赖传递呀!

武三通最近收养了一个义女,叫阿沅,此女自幼父母双亡,十分孤苦,武三通对他一直疼爱有加,不光教她武术,还教她编程,想着日后等阿沅长大了,也可以当个程序媛什么的,作...

823
来自专栏IT大咖说

Mars在移动网络的探索和实践

摘要 Mars这个名字来自于电影《火星救援》,它是一个结合移动 App 所设计的基于 socket 层的解决方案,在网络调优方面有着更好的可控性。微信高级工程师...

3577
来自专栏信安之路

信安之路挑战赛红蓝对抗题目全解析

首先,题目其实设置不是太难,主要是坑有点多,而且需要一定的时间才能完成。因为要本着贴近实战的原则出题,所以在做题的时候,很多人还是带着做传统 CTF 题目的思路...

6533
来自专栏北京马哥教育

Python数据挖掘:WordCloud词云配置过程及词频分析

豌豆贴心提醒,本文阅读时间5分钟 这篇文章是学习了老曹的微信直播,感觉WordCloud对我的《Python数据挖掘课程》非常有帮助,...

4848
来自专栏Java进阶干货

Tomcat中用JNDI方式加载JDBC DataSource以连接数据库

下载与所要连接的数据库版本对应的JDBC驱动程序,加入到应用的CLASSPATH。如果用tomcat部署,tomcat中最好也加上(笔者觉得好像没必要加,可是不...

1752

扫码关注云+社区

领取腾讯云代金券