1.什么是热修复
热修复,又称热补丁,一般是用事先定义好的接口,从网络下载代码并更新客户端代码,从而在用户无感知、也无需重装App的情况下,实现动态修复或动态更新。
2.为什么需要热修复
对开发人员:
快速作用,方便测试和反馈,节省应用发布时间,缩短开发周期,降低开发成本;
方便数据统计和ABTest,有利于更好地改进App。
对用户:
无感知,无需重新下载安装,用户体验更好。
3.怎样实现热修复
目前较为成熟的方案主要有两种:
1).Classloader替换类方案(以NUWA或RocooFix为例)
原理:如果多个dex里有相同的class,那么虚拟机会优先使用最先加载的dex中的class。所以将有问题的类打包到一个新dex(pathc.dex)中,然后下发给App,App 启动时将该patch.dex插入到其他dex前面优先加载,就达到了替换有问题class的目的。
难点一:改变dex加载顺序。我们可以通过DexClassLoader对象将补丁dex对象加载进来,再通过反射将补丁dex插入到dexElements最前面即可。如下:
首先分别获取到宿主应用和补丁的dex中的PathList.dexElements,并把两个dexElements数组做拼接,将补丁数组放在前面,最后将拼接后的数组再赋值回Classloader。
难点二:防止class被打上class_ispreverified标记。
首先解释这个标记。我们知道当一个apk在安装的时候,apk中的classes.dex会被虚拟机(dexopt)优化成odex文件,然后才会拿去执行。dex转化成odex时会执行dvmVerifyClass进行类的校验,如果一个类和它直接引用到的类都在一个dex里,则它会被打上class_ispreverified标记,表示不需要去其他dex中加载类了。因此一旦我们要修复的类出现在被打上该标记的类中,修复就会失效。
解决方法就是,编译时通过脚本的字节码操作,在所有类的构造方法中插入一段代码,让所有的类都引用一个单独dex的一个类,这样所有的类都不会标记class_ispreverified了。不过这也就失去了class_ispreverified的意义,会有性能上的影响。
总结:该方案可以在class层级上做修复,成功率较高,兼容性也较好。但是由于强制使每个类都引用了其它dex的类,会造成一定的性能损失。
2).Native hook方案(以AndFix为例)
原理:
该方案首先通过对比修改前后的apk文件得出两个dex文件中同时存在的方法,如果修改过,则利用自定义的Annotation(MethodReplace)标注,最后将这些修改过的方法打包成补丁文件。然后,在将补丁下发到App后,就可以跟据补丁文件中的注解来找到所有需要替换的方法,然后调用native方法去实现方法的替换。如下图:
替换方法的关键在于native层怎么影响内存里的java代码。我们知道,在java代码里将一个方法声明为native方法时,对此函数的调用就会到native层找。本方案原理就是将一个不是native的方法修改成native方法,然后在native层进行替换,通过dvmCallMethod_fnPtr函数指针来调用libdvm.so中的dvmCallMethod()来加载替换后的新方法,达到替换方法的目的。
替换方法的native实现如下:
总结:该方案是在method层级上做修复,不需要App重启即可生效。但它也有其局限性,如无法添加新类、无法添加或修改成员变量等。
4.两种实现的比较
以下是两个方案的区别列表:
框架名 |
修复级别 |
需要重启App |
性能损耗 |
补丁包体积 |
支持MultiDex |
有无签名校验 |
NUWA |
class级 |
是 |
较大 |
较大 |
是 |
无 |
AndFix |
method级 |
否 |
较小 |
较小 |
否 |
有 |
另外,NUWA和AndFix这两种方案都有较好的兼容性,同时支持art和dalvik模式,支持Android 6.0。
5.结论
NUWA和AndFix是当前相对比较成熟的热修复方案。NUWA的修复成功率较高,但是不能实时生效,对性能也有较大影响;而AndFix可以实时生效,但修复范围有限制。他们各有优劣,需要根据具体的需求来选择。
另外,微信开发团队的热修复方案"Tinker"也计划在今年开源。由其官方分享的文章来看,它采用差量更新dex文件方法来达到修复目的,效果也值得期待。
参考文章:
安卓App热补丁动态修复技术介绍:http://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=0
Android 热修复,没你想的那么难:http://kymjs.com/code/2016/05/08/01
微信Android热补丁实践演进之路:http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=2649286306&idx=1&sn=d6b2865e033a99de60b2d4314c6e0a25&scene=23&srcid=0705vd1zLzQEHZ9G6JyQSqTG#rd
Android热修复方案研究:http://www.voidcn.com/blog/u014077888/article/p-5019660.html
各大热补丁方案分析和比较:http://blog.zhaiyifan.cn/2015/11/20/HotPatchCompare/
[Android热修复] 技术方案的选型与验证:http://www.jianshu.com/p/1683c4e6f36d
Android热补丁之AndFix原理解析:http://w4lle.github.io/2016/03/03/Android%E7%83%AD%E8%A1%A5%E4%B8%81%E4%B9%8BAndFix%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/
原文:https://www.cnblogs.com/noodleutopia/p/5784831.html