美文网首页
【Android】【框架】【编译】【Freeline】

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

作者: 徐乙_ | 来源:发表于2019-08-26 23:50 被阅读0次

    整体架构

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

    传统打包流程

    image.png

    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作为默认的构建方案
    (拓扑+多任务并发,是非常重要的思想,我的前同事基于此思想开发出了启动优化框架)

    整体任务

    image.png

    分为如下几块

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

    默认8线程并发

    单工程任务

    image.png

    首先扫描文件变化
    然后根据扫描结果,考虑运行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

    image.png

    资源增量

    兼容增量包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

    image.png

    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

    相关文章

      网友评论

          本文标题:【Android】【框架】【编译】【Freeline】

          本文链接:https://www.haomeiwen.com/subject/xrgjectx.html