APK执行过程
代码编译形成APK的过程中,其实在里面生成了一个classes.dex文件,解压APK文件如下图:
APK结构
这个classes.dex文件就是所有代码的集合,是一个可执行文件,apk运行过程实质上是解压apk运行classes.dex这个文件。
apk首次运行的时候会对这个dex文件进行优化,优化后生成一个odex文件,存在于缓存中,下次再启动就直接打开这个odex文件,达到快速打开目的。而执行apk的过程就是遍历这个dex并作出相应操作的过程,遍历后的dex方法存放在一个Elements数组中,它的长度限制是65536.即日常说的65K.
如果我们apk因为太庞大或者是引用三方库太多导致方法数超过65K,就会报错.
而谷歌已经在Android 5.0开始支持Multdex.
热更新原理
Android类的加载流程是,遍历dexElements数组,一个类如果能被成功加载,那么它的dex一定 会出现在dexElements所对应的dex文件中,并且dexElements中出现的顺序也很重要,在dexElements前面出现的dex会被优先加载,一旦Class被加载成功, 就会立即返回。所以热修复原理基本都是通过修改dexElements中的dex加载来达到热修复的目的。下面是三种主流的热更新方案:
1.QQ空间超级补丁
原理:基于DEX分包方案,使用了多DEX加载的原理,把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面,让虚拟机去加载修复完后的方法。当patch.dex中包含Test.class时就会优先加载,在后续的DEX中遇到Test.class的话就会直接返回而不去加载,这样就达到了修复的目的。
QZone
2.微信Tinker
简单来说,在编译时通过新旧两个Dex生成差异path.dex。在运行时,将差异patch.dex重新跟原始安装包的旧Dex还原为新的Dex。这个过程可能比较耗费时间与内存,所以我们是单独放在一个后台进程:patch中。为了补丁包尽量的小,微信自研了DexDiff算法,它深度利用Dex的格式来减少差异的大小。
Tinker
3. AndFix
不同于QQ空间超级补丁技术和微信Tinker通过增加或替换整个DEX的方案,提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启,对应用无性能消耗的目的。
AndFix
AndFix流程如下:
AndFix流程