流程是这样:
创建(patch)-----merge-------加载(运行期间)
patch结构:文件里边包括两类:
一类是主apk的更新,以.so文件形式存在。
为什么使用.so文件?
新构建的APK有一个新的点,就是新增LIB目录,它里面有.SO文件,分arm与x86,
这些.SO都是正常的apk,做成.so文件,只是想在安装时,借助系统的能力从apk中解压出来。
一类是bundle的更新,以包名为文件夹存在,文件夹里包括
merge:
一主apk的merge,它还是分dalvik与art的不同的,
主Apk的Merge在dalvik和art上使用的机制有所不同,dalvik设备上没有任何merge过程,直接把libcom_taobao_maindex.so以bundle的形式安装到com.taobao.maindex目录下 Art设备上我们会根据source的apk(主apk的merge永远是基于基线版本)把classes.dex 提取出来以多dex的方式追加到libcom_taobao_maindex.so中,如果本身是多dex机制的,那么会将多个子dex全部追加进去,patch里面的classes.dex保持不变,source里面的dex的序列号往后偏移一位(classes.dex->classes2.dex,classes2.dex->classes3.dex)
bundle的merge
然后是安装
bundle安装到哪里去了?
运行期间的结构:
data/data/bundle的包名/version.1下
里边都有什么内容呢?classes.dex,.so文件内容
类加载机制
1、bundle加载
先把最高版本进行加载,只保留最近两个版本
2、主apk加载
把新的变化内容加到
双亲委派机制去findclass然后去loadclass。通过dexfile类去loadclas
dalvik:把新的dev添加到数组的前边,这样就替换了。
art:虚拟机不行:
新老dex进行merge,这样patch中的dex包括原程序在内的所有dex.
真正做的时候遇到 的问题:
一、andrdoid类之间的引用有一个预校验的过程,引用的类需要与自己在一个dex里面。
很显示我们肯定是一个新dex,所以解决办法
在主apk中所有类与接口添加 一段代码,意思是给每个类引用到一个不存在的类,以解除预校验。
二、
OAT的限制:
android到art后原有的dexopt会改为dex2oat,运行时代码由原来的解释执行改为直接运行native代码,之前的使用过程中发现单纯得往前面追加patch的dex并不能完全解决动态部署的问题
因为可能新的虚拟机直接在native层执行class代码。而不是去新加载loadclass然后再执行。
所以采取的策略是新老merge,这样patch中的dex包括原程序在内的所有dex.
三、资源问题解决:
因为android机制是读到一个资源就去检验ID,如果不存在的话,就会报错。也就是说不支持新增ID
修改了aapt的工具,在基包里TYPE类型里预留了128个ID供扩展使用。相同的资源替换,新增的增加