【Android】【框架】【编译】【Freeline】

整体架构

1、核心原理
热更新技术在编译期的应用,后期引用到了线上做热更新
2、稳定性
完善的基线对齐、进程级别异常隔离
3、性能
借鉴Buck多任务并发思想,端口扫描、代码扫描、并发编译、并发dx、并发merge dex,在多核机器上加速明显
在class、dex、resource方面做了缓存
优化buck加速dx、DexMerger、资源编译方面,深入改造AAPT流程
4、具有能力
多任务并发,多级缓存,增量范围最小化,懒加载,基于长链接无安装式运行期动态替换,基线对齐触发机制,可调试

 

传统打包流程

AAPT会执行2次
第一次生成R.java,进行javac编译
第二次对res里的资源进行编译
最后APKBuilder把编译好的资源、DEX文件打包成APK,签名,安装
整个流程没有缓存,没有多任务处理,没有增量

 

LayoutCast

通过AS插件、Python脚本,把diff进行编译和打包,生成classes.dex和res.zip,通过adb发送这2个文件,再进行替换
有不足的地方:

  1. 传统流水式构建,不支持多任务,不能很好地利用该多核优势
  2. res变化后,LayoutCast的行为与instant-run一致,重新打资源包,然后推送至手机,若资源包过大,TCP传输速度会很慢
  3. 通过运行时反射R class field来生成ids.xml、public.xml,用于保证增量包res id和全量包res id一致。因为R的id太多,反射耗时太久
  4. 某些情况下AAPT构建时可能发生数组越界,运行时
  5. 没有缓存机制
  6. 代码增量插入在系统dexlist最前端位置,4.x上手机校验不通过

 

Buck

以工程为单位拆分出多个任务,并发执行,梳理好节点的依赖关系,输出有向拓扑图
建立了细化的缓存系统
增量构建的原理在于,以工程目录为单位构建,发生变更的时候,重新走一次合并各工程dex,对齐,签名
侵入性较强
在FaceBook内部、微信都是用Buck作为默认的构建方案
(拓扑+多任务并发,是非常重要的思想,我的前同事基于此思想开发出了启动优化框架)

 

整体任务

分为如下几块

  1. 电脑手机建立长连接
  2. 扫描各个子工程文件变化
  3. 各个子工程增量dex构建
  4. 增量资源包构建
  5. 合并所有工程dex
  6. 传输增量包

默认8线程并发

 

单工程任务

首先扫描文件变化
然后根据扫描结果,考虑运行inc-code-task、inc-res-task

inc-code-task

  1. check-r-change:检验R文件MD5是否变化,若有变化,把新的R.java加入变更列表
  2. begin-code-transaction:备份工作空间,在后续步骤出错时,进行回滚
  3. javac:把扫描出来的Java变更部分,编译
  4. buck-dx:.class打包成.dex。该工具比Android原生快40%左右
  5. buck-smart-dex:减小dex体积

inc-res-task

  1. begin-res-transaction:备份
  2. merge xml:对同名xml节点合并
  3. merge ids:若gen-r阶段发现R文件变更,或者更改文件集合里有ids.xml或者public.xml,则对于新老的这些文件,进行merge
  4. gen ids:通过最后一次生成的资源包,反向生成ids.xml和public.xml,该两个文件在构建增量资源包时候参与编译,可以使得 最后构建出来的资源包的内对于的资源ID与前一次构建的资源包保持一致
  5. build-inc-res:构建增量包

 

多级缓存

对class、dex做缓存,这个过程并不复杂,做个缓存而已
对于res,增量包构建后,会和手机端的资源文件做一次sync
在做完缓存与拓扑多任务后,性能已经很卓越了

 

代码增量

通过植入Dex到DexList,这是经典的热修复原理
对于类的查找,会从DexList的开始进行查找,找到后就不会再往下找了,基于此实现动态替换dex

 

资源增量

兼容增量包res id、基线包res id

采用上一次生成的public.xml、id.xml参与后续编译

  1. 运行期反射R class field的放啊不可靠,资源太多,耗时太久
  2. ApkTool反编译资源包,把所有资源逆向导出
  3. 对R.java,通过id-gen-tool工具,反向导出id.xml、public.xml,并且会过滤掉枚举常量,解决内存越界问题

高效构建diff res包

根据生成的id.xml、public.xml,放进values中,参与编译后,可以生成正确的resoucres.arsc,不需要编译layout资源和AndroidManifest.xml
并且做了缓存
打包时仅对修改的文件编译后的资源进行打包
最终构建出来diff res包、resoucres.arsc、AndroidManifest.xml

增量包在手机生效

res支持以目录形式存在,所以:
1、解压基线包apk
2、修改AssetsManager对应的path
3、进行sync

4、清空Resources的cache,重新构建Resources

 

绕过CLASS_ISPREVERIFIED限制

安装包安装的时候,dexopt会扫描dex内的class,class文件内所有直接引用到的类
如果和该class在同一个dex中,会被打上CLASS_ISPREVERIFIED标签
被打上这个标记的类,DVM在运行时检查,若发现引用的类和打标记的类不在同一个dex,会报错
所以只需要对每个class通过ASM引用一个外部dex类即可

 

后记

有什么写得错误、让人费解或遗漏的地方,希望可以不吝赐教,我会马上更改

 

学习自

https://yq.aliyun.com/articles/59122?spm=a2c4e.11153940.0.0.351439d5GMvMx1&type=2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值