加入收藏 | 设为首页 | 会员中心 | 我要投稿 武汉站长网 (https://www.027zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 传媒 > 正文

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

发布时间:2016-09-12 15:15:12 所属栏目:传媒 来源:站长之家用户
导读:某APP的启动载入时间为3s左右,本身就是基于多DEX模式的实现。

2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案、阿里AndFix以 及微信Tinker,它们在原理各有不同,适用场景各异,到底采用哪种方案,是开发者比较头疼的问题。本文希望通过介绍QQ空间补丁、Tinker以及基于AndFix的阿里百川HotFix技术的原理分析和横向比较,帮助开发者更深入了解热修复方案。

技术背景

一、正常开发流程

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

从流程来看,传统的开发流程存在很多弊端:

· 重新发布版本代价太大

· 用户下载安装成本太高

· BUG修复不及时,用户体验太差

二、热修复开发流程

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

而热修复的开发流程显得更加灵活,优势很多:

· 无需重新发版,实时高效热修复

· 用户无感知修复,无需下载新的应用,代价小

· 修复成功率高,把损失降到最低

业界热门的热修复技术

热修复作为当下热门的技术,在业界内比较著名的有阿里巴巴的AndFix、Dexposed,腾讯QQ空间的超级补丁和微信的Tinker。最近阿里百川推出的HotFix热修复服务就基于AndFix技术,定位于线上紧急BUG的即时修复,所以AndFix技术这块我们重点分析阿里百川HotFix。下面,我们就分别介绍QQ空间超级热补丁技术和微信Tinker以及阿里百川的HotFix技术。

一、QQ空间超级补丁技术

超级补丁技术基于DEX分包方案,使用了多DEX加载的原理,大致的过程就是:把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。

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

当patch.dex中包含Test.class时就会优先加载,在后续的DEX中遇到Test.class的话就会直接返回而不去加载,这样就达到了修复的目的。

但是有一个问题是,当两个调用关系的类不在同一个DEX时,就会产生异常报错。我们知道,在APK安装时,虚拟机需要将classes.dex优化成odex文件,然后才会执行。在这个过程中,会进行类的verify操作,如果调用关系的类都在同一个DEX中的话就会被打上`CLASS_ISPREVERIFIED`的标志,然后才会写入odex文件。

所以,为了可以正常地进行打补丁修复,必须避免类被打上`CLASS_ISPREVERIFIED`标志,具体的做法就是单独放一个类在另外DEX中,让其他类调用。

我们来逆向手机QQ空间APK看一下具体的实现:

先进入程序入口`QZoneRealApplication`,在`attachBaseContext`中进行了两步操作:修复`CLASS_ISPREVERIFIED`标志导致的unexpected DEX problem异常、加载修复的DEX。

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

 1. 修复Unexpected DEX Problem异常

先看代码,

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

可以看到,这里是要加载一个libs目录下的dalvikhack.jar。在项目的assets/libs找到该文件,解压得到’classes.dex’文件,逆向打开该DEX文件,

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

通过不同的DEX加载进来,然后在每一个类的构造方法中引用其他DEX中的唯一类AnitLazyLoad,避免类被打上CLASS_ISPREVERIFIED标志。

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

在无修复的情况下,将DO_VERIFY_CLASSES设置为false,以提高性能。只有在需要修复的时候,才设置为true。

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

至于如何加载进来,与下面第二个步骤基本相同。

2. 加载修复的DEX

从loadPatchDex()方法进入,经过几次跳转,到达核心的代码段,`SystemClassLoaderInjector.c()`。由于进行了混淆和多次方法的跳转,于是将核心代码段做了如下整理:

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

修复的步骤为:

1. 可以看出是通过获取到当前应用的Classloader,即为BaseDexClassloader

2. 通过反射获取到他的DexPathList属性对象pathList

3. 通过反射调用pathList的dexElements方法把patch.dex转化为Element[]

4. 两个Element[]进行合并,把patch.dex放到最前面去

5. 加载Element[],达到修复目的

整体的流程图如下:

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

从流程图来看,可以很明显的找到这种方式的特点:

优势:

1.  没有合成整包(和微信Tinker比起来),产物比较小,比较灵活

2.  可以实现类替换,兼容性高。(某些三星手机不起作用)

不足:

1. 不支持即时生效,必须通过重启才能生效。

2. 为了实现修复这个过程,必须在应用中加入两个dex!dalvikhack.dex中只有一个类,对性能影响不大,但是对于patch.dex来说,修复的类到了一定数量,就需要花不少的时间加载。对手淘这种航母级应用来说,启动耗时增加2s以上是不能够接受的事。

3. 在ART模式下,如果类修改了结构,就会出现内存错乱的问题。为了解决这个问题,就必须把所有相关的调用类、父类子类等等全部加载到patch.dex中,导致补丁包异常的大,进一步增加应用启动加载的时候,耗时更加严重。

二、微信Tinker

微信针对QQ空间超级补丁技术的不足提出了一个提供DEX差量包,整体替换DEX的方案。主要的原理是与QQ空间超级补丁技术基本相同,区别在于不再将patch.dex增加到elements数组中,而是差量的方式给出patch.dex,然后将patch.dex与应用的classes.dex合并,然后整体替换掉旧的DEX文件,以达到修复的目的。

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

我们来逆向微信的APK看一下具体的实现:

(编辑:武汉站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读