哥哥⼿把⼿教你Android热更新,到底是更新啥?
正常开发流程:
新版本上线,发现问题或⽤户反馈bug,紧急修复,上线版本,⽤户重新安装。
热修复流程:
新版本上线,发现问题或⽤户反馈,紧急修复,上线补丁,⾃动修复
Thinker解决思路?
在android5.0之前,每个android应⽤只含有⼀个dex⽂件,dex的⽅法数量被限制在了65535之内,导致apk引⼊⼤量第三⽅sdk后⽅法数量超过限制⽆法编译通过。为了解决这个问题,Google推出多dex⽂件的解决⽅案multidex,⼀个apk可以包含多个dex⽂件。通过Multidex.install(this)完成dex⽂件的加载。
Tinker⽅案参考multidex实现原理,在编译时通过新旧两个Dex⽣成差异patch.dex。在运⾏时,将差异patch.dex重新和原始安装包的旧Dex合并还原为新的Dex。这个过程可能⽐较耗费时间与内存,所以tinker单独放在⼀个后台进程:patch中处理。为了补丁包尽量的⼩,⾃研了DexDiff算法,它深度利⽤Dex的格式来减少差异的⼤⼩。由于采⽤ClassLoader机制,所以需要app重启。
Tinker基于基版本利⽤⾃研的DexDiff算法⽣成差分包,放在后台。App启动时下载差分包,与原dex重新合并,解压缩,并参考MultiDex.install()流程,重新安装app。安卓app开发用什么框架
由于类加载实现原理涉及dex⽂件的重新解压缩合并等处理,消耗内存⼤,耗时长,在系统低内存时容易导致热更新失败,腾讯测试成功率⼤概为95%。实际热部署时,差分包应⽂件⼤⼩最⼩。
综上没有完美的热更新⽅案,没有100%的热更新成功率。⽬前,腾讯tinker基本可以满⾜app的热更新需求,但随着app⽤户规模不断增⼤,业务需求⽇益复杂,可考虑阿⾥的sophix商业⽅案,sophix同时应⽤类加载和底层替换两种⽅案,具有底层替换的修改及时性,和类加载⽅案的兼容性等优点。⽽且sophix采⽤⾮侵⼊打包,图形化的⽣成补丁,⽤阿⾥的原话说就是“傻⽠式接⼊”,点⼀点⿏标就能⽣成补丁⽂件,⽽且阿⾥提供了后台补丁管理系统,帮助开发者在⽣成补丁后直接上传⾄阿⾥的后台,⽆需开发者在⾃⼰的app和服务端做任何的操作。
热部署” – ⽅法内的简单修改,⽆需重启app和Activity。 “暖部署
暖部署” – app⽆需重启,但是activity需要重启,⽐“热部署
冷部署” – app需要重启,⽐如继承关系的改变或⽅法的签名变化等。
如资源的修改。 “冷部署
热更新究竟是什么?
有⼀些这样的情况, 当⼀个App发布之后,突然发现了⼀个严重bug需要进⾏紧急修复,这时候公司各⽅就会忙得焦头烂额:重新打包App、测试、向各个应⽤市场和渠道换包、提⽰⽤户升级、⽤户下载、覆盖安装。有时候仅仅是为了修改了⼀⾏代码,也要付出巨⼤的成本进⾏换包和重新发布。
这种需要替换运⾏时新的类和资源⽂件的加载,就可以认为是热操作了。⽽在热更新出现之前,通过反射注解、反射调⽤和反射注⼊等⽅式已经可以实现类的动态加载了。⽽热更新框架的出现就是为了解决这样⼀个问题的。从某种意义上来说,热更新就是要做⼀件事,替换。当替换的东西属于⼤块内容的时候,就是模块化了,当你去替换⽅法的时候,叫热更新,当你替换类的时候,加热插件,⽽且重某种意义上讲,所有的热更新⽅案,都是⼀种热插件,因为热更新⽅案就是在app之外去⼲这个事。就这么简单的理解。⽆论是替换⼀个类,还是⼀个⽅法,都是在⼲替换这件事请。。这⾥的替换,也算是⼏种hook操作,⽆论在什么代码等级上,都是⼀种侵⼊性的操作。
对已发布app进⾏bug修复的技术)
改变app运⾏⾏为的技术!(或者说就是对已发布app进⾏bug修复的技术
所以总结⼀句话简单理解热更新 HotFix 就是改变app运⾏⾏为的技术
⽬前存在的主流框架?
先后出现了Dexposed、AndFix,Qzone超级补丁的类Nuwa⽅式,的Tinker, ⼤众点评的nuwa、百度⾦融的rocooFix, 饿了么的amigo以及美团的robust.以及阿⾥的Sophix.腾讯的内部⽅案KKFix.
框架横向对⽐?
实现套路?
对⽐点评?
AndFix作为native解决⽅案,⾸先⾯临的是稳定性与兼容性问题,更重要的是它⽆法实现类替换,它是需要⼤量额外的开发成本的;
Robust兼容性与成功率较⾼,但是它与AndFix⼀样,⽆法新增变量与类只能⽤做的bugFix⽅案;
Qzone⽅案可以做到发布产品功能,但是它主要问题是插桩带来Dalvik的性能问题,以及为了解决Art下内存地址问题⽽导致补丁包急速增⼤的。
特别是在Android N之后,由于混合编译的inline策略修改,对于市⾯上的各种⽅案都不太容易解决。⽽Tinker热补丁⽅案不仅⽀持类、So以及资源的替换,它还是2.X-8.X(1.9.0以上⽀持8.X)的全平台⽀持。利⽤Tinker我们不仅可以⽤做bugfix,甚⾄可以替代功能的发布
类加载机制?
我们知道Android系统也是仿照java搞了⼀个虚拟机,不过它不叫JVM,它叫Dalvik/ART VM他们还是有很⼤区别的(这是不是我们的重点, 点开是个拓展阅读)。我们只需要知道,Dalvik/ART VM 虚拟机加载类和资源也是要⽤到ClassLoader,不过Jvm通过ClassLoader加载的class字节码,⽽Dalvik/ART VM通过ClassLoader加载则是dex。
Android的类加载器分为两种,PathClassLoader和DexClassLoader,两者都继承⾃BaseDexClassLoader
PathClassLoader代码位于libcore\dalvik\src\main\Java\dalvik\system\PathClassLoader.java
DexClassLoader代码位于libcore\dalvik\src\main\java\dalvik\system\DexClassLoader.java
BaseDexClassLoader代码位于libcore\dalvik\src\main\java\dalvik\system\BaseDexClassLoader.java
PathClassLoader
⽤来加载系统类和应⽤类
DexClassLoader
⽤来加载jar、apk、dex⽂件.加载jar、apk也是最终抽取⾥⾯的Dex⽂件进⾏加载.
归纳⼀下就是:ClassLoader会遍历这个数组,然后加载这个数组中的dex⽂件.
⽽ClassLoader在加载到正确的类之后,就不会再去加载有Bug的那个类了,我们把这个正确的类放在Dex⽂件中,让这个Dex⽂件排在dexElements数组前⾯即可.
为什么推荐Sophix?
为了提升产品在敏捷开发下的最佳发布体验,分别尝试了备受关注的阿⾥和两⼤派系的热更新⽅案(⽀付宝的Andfix和的Tinker),但在探索的过程中,发现两种⽅案都存在弊端,如使⽤场景有限,修复成功率低,存在兼容问题。加之各⽅案还在内部快速迭代,均未能达到商业化的标准,所以热修复在项⽬中的应⽤被暂时搁置了。
直到最近,看到阿⾥推出了⾮侵⼊式热修复框架Sophix。Sophix对其前辈Andfix,阿⾥百川Hotfix等⽅案进⾏了升级改造,打破了旧⽅案诸多限制,涵盖了代码修复,资源修复,So库修复。加上阿⾥云平台的⽀持,经过简单的配置就可接⼊使⽤,⽬之所及,Sophix已经成为⽬前成熟度最⾼的热修复框架。这也让我重新燃起了对热更新及底层技术探索的热情。所以我想以此为契机,⽤系列⽂章的形式,围绕热点技术所涉猎的知识进⾏由浅⼊深的持续挖掘。
修复⽴即⽣效,是热修复所追求的,底层替换⽅案通过在运⾏时利⽤hook操作native指针实现“热”的特性。但这⾥有⼀个关键点,底层替换所操作的指针,实际上是ArtMethod,在类被加载,类中的每个⽅法都会有对应的ArtMethod,它记录了⽅法包括所属类和内存地址信息,Andfix正是通过篡改ArtMethod,将补丁⽅法ArtMethod的成员值逐⼀赋给旧⽅法,实现替换。问题就出现在这个逐⼀上。因为Andfix的ArtMethod⽅法结构是根据Android开源代码写死的,⾯对国内⼚商的定制,经常会导致两者ArtMethod⽅法结构不⼀致,这也是兼容问题产⽣的根本原因。
为了解决这个问题,Sophix采⽤了对旧ArtMethod进⾏完整替换,通过动态测量ArtMethod的size(通过c层的mempy(dest ,src ,size)⽅法),进⾏全量拷贝。这样做⽆论ArtMethod被修改成什么样,只需要统⼀执⾏拷贝,就可以完成替换,完全⽆视修改虚拟机导致的ArtMethod结构差异.
底层替换虽能使修复即时⽣效,但由于类加载后,⽅法结构已固定,这就造成使⽤上会有诸多限制。相反类加载⽅案的使⽤场景更为⼴泛。Sophix使⽤类加载作为兜底⽅案。在热部署⽆法使⽤的情况下,⾃动降级为冷部署⽅案。
⽆论是冷部署还是热部署,都需要通过同⼀套补丁兼顾,在Art虚拟机下,默认⽀持多dex加载,虚拟机会优先加载命名为classes.dex的⽂件。Sophix利⽤了这⼀点,将补丁⽂件命名为classes.dex,并对原有dex⽂件进⾏排序。这样⼀来,art虚拟机就会先加载补丁⽂件,后续加载的同类名的类会被忽略,最后将加载得到的dexFile把dexElements整体替换。
Dalvik虚拟机下情况则有些不同,Dalvik默认只加载classes.dex,其他dex则被忽略。那么,Sophix就需要⼀个全量dex,前⾯提到tinker 采⽤⾃主研发的dexDiff技术,从⽅法和指令的维度进⾏dex合成,但Dex合成过程发⽣在虚拟机堆内存上,修复的成功率极⼤的受到性能问题的影响。为了解决这个问题,Sophix换了⼀种思路,从类的维度,对照补丁包中出现的类,在原有包中做删除操作,如图。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论