HTML5技术

APP热更新方案 - 大熊先生|互联网后端技术(2)

字号+ 作者:H5之家 来源:H5之家 2017-06-15 09:01 我要评论( )

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

当两个调用关系的类不在同一个DEX时,就会产生异常报错。我们知道,在APK安装时,虚拟机需要将classes.dex优化成odex文件,然后才会执行。在这个过程中,会进行类的verify操作,如果调用关系的类都在同一个DEX中的话就会被打上CLASS_ISPREVERIFIED的标志,然后才会写入odex文件。具体如何解决这个问题可以参见QQ空间终端开发团队QQ空间终端开发团队发布的” 安卓App热补丁动态修复技术介绍”

 

优缺点:

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

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

不足:

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

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

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

 

 

微信Tinker

根据微信内部人士介绍:微信tinker项目之初最大难点在于如何突破Qzone方案的性能问题,通过研究Instant Run的冷插拔与buck的exopackage给了我们灵感。它们的思想都是全量替换新的Dex

 

因为使用全新的dex,所以自然绕开了Art地址可能错乱的问题,在Dalvik模式下也不需要插桩,加载全新的合成dex即可。

焦点问题是合并的过程会不会有问题,会不会耗时或者效率低? 为此腾讯在DEX方面也花了很多时间研究内部的格式以及如何做Merge和进行校验工作,详细了解可以查看” 大腾讯的第一个开源项目「Tinker」”这篇文章

优势:

1. 合成整包,不用在构造函数插入代码,防止verify,verify和opt在编译期间就已经完成,不会在运行期间进行

2. 性能提高。兼容性和稳定性比较高。

3. 开发者透明,不需要对包进行额外处理。

不足:

1. 与超级补丁技术一样,不支持即时生效,必须通过重启应用的方式才能生效。

2. 需要给应用开启新的进程才能进行合并,并且很容易因为内存消耗等原因合并失败。

3. 合并时占用额外磁盘空间,对于多DEX的应用来说,如果修改了多个DEX文件,就需要下发多个patch.dex与对应的classes.dex进行合并操作时这种情况会更严重,因此合并过程的失败率也会更高。

 

 

阿里Andfix方案

为何唯独Andfix能够做到即时生效呢?

原因是这样的,在app运行到一半的时候,所有需要发生变更的Class已经被加载过了,在Android上是无法对一个Class进行卸载的。而腾讯系的方案,都是让Classloader去加载新的类。如果不重启,原来的类还在虚拟机中,就无法加载新类。因此,只有在下次重启的时候,在还没走到业务逻辑之前抢先加载补丁中的新类,这样后续访问这个类时,就会Resolve为新的类。从而达到热修复的目的。

Andfix采用的方法是,在已经加载了的类中直接在native层替换掉原有方法,是在原来类的基础上进行修改的。

以Art为例,每一个Java方法在art中都对应着一个ArtMethod,ArtMethod记录了这个Java方法的所有信息,包括所属类、访问权限、代码执行地址等等。通过env->FromReflectedMethod,可以由Method对象得到这个方法对应的ArtMethod的真正起始地址。然后就可以把它强转为ArtMethod指针,从而对其所有成员进行修改。

这很C/C++ 研发的味道,实际上Andfix的核心代码replaceMethod就是用cpp写的。

 

面临的挑战:

因为安卓各ROM乱象的原因,ArtMethod的结构可能会不一样, ArtMethod类包含些什么其实都是在编译阶段,在运行阶段可能不是这么回事,例如sizeof(ArtMethod)可能实际在各平台就完全不一样,但是我们在编译的时候就确定了值,直接操作容易改乱内存数据导致奔溃。

有什么好的方法来解决这个问题呢?

来看看奇技淫巧

由于f1和f2都是static方法,所以都属于direct ArtMethod Array。由于NativeStructsModel类中只存在这两个方法,因此它们肯定是相邻的。

那么我们就可以在JNI层取得它们地址的差值:

然后,就以这个methSize作为sizeof(ArtMethod),代入之前的代码。

问题就迎刃而解了。即使以后的Android版本不断修改ArtMethod的成员,只要保证ArtMethod数组仍是以线性结构排列就能完美兼容。

著:此方法最新方案并不在开源的方案中

 

最大的优势在于

1. BUG修复的即时性

2. 补丁包同样采用差量技术,生成的PATCH体积小

3. 对应用无侵入,几乎无性能损耗

不足:

1. 不支持新增字段,以及修改<init>方法,也不支持对资源的替换。

 

 

再来看看IOS的热更新技术:

苹果把加载动态库的功能给封了,动态库必须跟随安装包一起签名才能被加载,无法通过别的途径签名后再下发。

 

Wax

最早要从 Wax 这个项目开始说,大家都知道 Objective-C 有着非常强大的动态特性。比如说:

•运行时构造类和方法

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 探讨SQL Server并发处理存在就更新七种解决方案 - Jeffcky

    探讨SQL Server并发处理存在就更新七种解决方案 - Jeffcky

    2017-06-01 17:00

  • 通用网页调用本地应用程序方案(windows平台) - 小龙女先生

    通用网页调用本地应用程序方案(windows平台) - 小龙女先生

    2017-05-16 13:00

  • 郁金香搜索引擎的方案 - 静儿1986

    郁金香搜索引擎的方案 - 静儿1986

    2017-04-29 10:00

  • 移动端WEBAPP开发遇到的坑,以及填坑方案!持续更新~~~~ - ygjoe

    移动端WEBAPP开发遇到的坑,以及填坑方案!持续更新~~~~ - ygjoe

    2017-04-16 11:00

网友点评
a