android 热修复威廉希尔官方网站
大小:0.2 MB 人气: 2017-09-27 需要积分:1
标签:
一、类加载方案1、Qzone
Qzone的超级热修复方案是业界最早的热修复方案之一,原理简单而巧妙,影响深刻而久远,在此简单介绍。Android类加载的源码如下:
可以看出当有多个dex文件时,他们会组成一个有序数组,按顺序加载,而对于一个已经加载的Class是不会再次加载的,由此得出热修复方案:把需要修复的类打包成一个dex文件下发,并在APP启动时通过反射,将这个dex文件放在dexElements的最前面,这样修复了的Class就会比有Bug的Class优先加载了。如下图所示:
但在实现过程中,会遇到unexpected DEX problem异常,Qzone方案为了解决这个问题采用了插桩的策略来规避这个异常。实际上,Android系统的检查和优化都是有其意义的,因此这种方法在Dalvik和Art上都会遇到问题。
● 在Dalvik虚拟机,APP在安装的时候会被执行dexopt操作,同一个dex文件内的Class会被打上CLASS_ISPREVERIFIED标志,而补丁包中的类并没有打上此标志,因此抛出异常。解决方法就是在第一次打包APK时让所有类都引用另一个dex文件中的类,这样所有的类始终不会打上CLASS_ISPREVERIFIED标志,因此补丁包可以顺利加载,但是Dalvik虚拟机在检测到一个类未打上CLASS_ISPREVERIFIED之后会再次在类加载的时候进行dexopt相关的操作,如果一次性加载很多类,速度将明显变慢。
● 在Art虚拟机,dex文件最终会编译成本地机器码,在dex2oat时fast *已经将各个类的地址写死,若补丁包中的类出现字段或者方法的修改,会出现内存地址错乱,解决办法是将这个类的父类和调用这个类的类都加入补丁包。但这样会导致补丁包急剧增大。(实际上要理解清楚这个问题需要熟悉Dalvik和Art的完整流程,并非三言两语能解释清楚)
这两个问题都可以解决,但都要付出一些代价:类加载速度或者补丁包大小。
2、Tinker
如果Qzone没有上面两个缺陷,或许就不会有Tinker了。对于微信这样一个对性能有极高要求的产品来说,Qzone的缺点会被无限放大。在参考Instant Run的冷插拔与buck的exopackage后,Tinker采用了全量替换的策略。全量替换可以避免插桩和地址写死问题,但是补丁包会很大,因此可以在新旧两个Dex的差异放在补丁包中,下发到移动端后再在本地合成完整的dex文件。
实际上,Tinker保留了Qzone最核心的东西:反射修改dexElements。无论是插入还是替换,本质都是利用了类加载的特点。由于需要下发的全量补丁包体积过大,Tinker采用了后台求diff,下发diff文件,移动端合成全量包的策略。
如果仅此而已,只要有diff/patch算法,就可以开发Tinker了。实际上,确实如此。而Tinker第二个创新之处就是采用了自研的DexDiff算法,大大优化了下发差异包的大小。
非常好我支持^.^
(0) 0%
不好我反对
(0) 0%