Skip to content

Jugg 工作原理

一次标准 Android Run 会经过 Gradle 配置、依赖解析、源码与资源编译、APK 打包签名、安装和启动。这个流程能够生成完整且可信的应用,但在连续修改少量代码时,其中许多步骤每轮都会重复执行。

Jugg 将完整 Gradle 构建作为增量起点。后续 Run 复用已经确认的工程信息和构建产物,只处理本轮变化及其影响范围,再把局部产物部署到设备。工程条件、产物或设备状态无法继续增量时,流程会更新 APK、恢复设备状态,或者重新执行 Gradle 构建。

text
可信 Gradle 基线

检查工程变化、构建目标和设备状态
  ├─ 适合增量 → 编译变化及受影响代码 → 按产物部署 → 成功后提交状态
  └─ 需要完整构建 → 执行 Gradle → 刷新本地基线 → 安装并重新对齐设备

Gradle 构建提供增量起点

Jugg 第一次接管 Run,或者发现当前状态已经不适合继续增量时,会执行完整 Gradle 构建。它从这次构建中获得后续增量需要的基础信息:

基线信息后续用途
当前模块、Variant、源码目录和编译参数判断哪些文件属于本次构建,以及该使用怎样的编译环境
依赖、类路径和生成代码让局部源码编译得到与 Gradle 构建一致的类型信息
APK、class、资源及其他构建产物为局部产物生成、APK 更新和设备部署提供起点

这些信息共同组成一份可信基线。Jugg 复用 Gradle 已经确认的结果,围绕本轮变化继续编译和部署。工程模型如何同步,见工程模型同步

每次 Run 先选择增量还是 Gradle

点击 Run 后,Jugg 会先检查本轮操作能否沿用现有基线,主要包括:

  • 构建目标、模块和 Variant 是否仍与基线一致;
  • Gradle 配置、依赖和编译环境是否发生了需要重新同步的变化;
  • 文件变化能否由当前增量编译器处理;
  • 本地记录与选中设备上的应用状态是否能够衔接。

条件满足时进入增量编译;需要刷新工程或完整产物时进入 Gradle 构建。部分依赖变化也可以直接生成增量部署产物,具体机制见依赖增量编译

这个决策发生在编译之前,因此当前工程状态会决定一次 Run 进入增量路径还是 Gradle 路径。完整编排过程见编译流水线

增量编译会扩展到受影响代码

进入增量路径后,Jugg 先按文件类型处理本轮变化,例如编译 Java、Kotlin 和资源文件,并保留 assets、native lib 等无需源码编译的文件供部署阶段处理。随后它会比较新旧 class 结构,并结合引用关系补充受影响源码。

例如,一个方法签名发生变化时,只重新编译定义该方法的文件可能留下仍按旧签名调用的 class。Jugg 会把相关调用方加入本轮编译,直到产物之间重新一致。编译器发现可恢复的缺失符号或结构变化时,还可以根据新的影响范围执行一次有针对性的重试。

这一阶段的输出是 class、资源、dex、依赖文件或 APK 更新数据等局部产物。完成设备部署后,这些产物才会成为下一轮的可信状态。各类输入的具体处理方式见增量编译部署数据与影响分析

部署方式由产物和设备共同决定

Jugg 根据本轮产物、设备能力和已有部署状态选择生效方式。在线替换只是其中一条路径。

本轮结果常见生效方式
可在线替换的代码和资源将局部产物发送到应用进程,并按需要刷新界面或重启 Activity
需要进程重新加载的代码结构变化重启应用进程,或者使用能够承载结构变化的热修复路径
Manifest、native lib 等需要写回安装包的内容基于现有 APK 更新对应条目,重新签名并安装
本地记录与设备状态不一致恢复部署快照、重新安装,或回到完整 Gradle 流程
完整 Gradle 构建产物安装完整 APK,并以新的构建结果作为后续基线

因此,“编译了哪些内容”和“这些内容怎样在设备上生效”是两个连续但独立的判断。部署策略还会考虑多 APK 归属、多设备状态和目标 Android 版本,详见部署策略兼容性部署

部署成功后才推进状态

连续增量依赖三类状态保持一致:

  • Gradle 基线描述完整工程和构建产物;
  • 本地增量记录描述哪些变化已经编译并准备部署;
  • 设备状态描述应用实际接收了哪些产物。

如果编译成功但部署失败,而本地仍把这批产物记录为已经生效,下一次 Run 就会从错误的起点继续计算。Jugg 因此把编译结果视为待提交数据:所有选中设备完成本轮部署后,才推进增量历史;失败时保留上一份可信记录,由后续恢复、重装或 Gradle 构建重新对齐。

text
编译成功 → 部署成功 → 提交本轮状态 → 成为下一次增量起点
          ↘ 部署失败 → 保留上次状态 → 恢复 / 重装 / Gradle

设备重启、应用数据清理或部署缓存丢失后的处理方式,见增量部署状态恢复

部署已经失败时,Retry、兼容部署、Recover 和重新安装的选择过程见部署自愈机制

回到 Gradle 会开始新的增量周期

Gradle 回退用于重新建立可信起点。完整构建会刷新工程快照、APK、编译产物和生成文件;安装成功后,设备也重新与这份构建结果对齐。下一次 Run 可以基于新的状态继续判断是否进入增量路径。

常见触发条件包括构建目标变化、工程配置超出当前增量能力、关键基线缺失,以及增量编译或部署无法可靠恢复。具体条件和用户可见结果见Gradle 回退与基线重建

继续阅读