bigywater.tech
Java · 332

构建缓存与增量编译

构建很慢,缓存怎么救?Maven 自带的增量编译到底增量到什么程度?构建缓存扩展按什么判断命中、命中之后跳过什么?这篇用一个小项目把每种情况的耗时和日志都量出来。

3.2 → 1.2 秒
clean verify 第一次(存入缓存)与第二次(命中缓存)的耗时
8 个
只改 1 个源文件时 Maven 重新编译的源文件数(整个模块)
6 个
命中缓存时被跳过的插件执行(含 surefire:test)

Maven 自带的增量

实测 · 本机执行输出
  第一次 mvn package(依赖与插件已在本地仓库)    3.1 秒
  第二次 mvn package(什么都没改)         2.8 秒  ['Nothing to compile - all classes are up to date.', 'Nothing to compile - all classes are up to date.', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.528 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0']
  只改 C3.java 之后 mvn package           3.1 秒  ['Compiling 8 source files with javac [debug release 21] to target/classes', 'Compiling 1 source file with javac [debug release 21] to target/test-classes', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.531 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0']
  mvn clean package                      3.1 秒  ['Compiling 8 source files with javac [debug release 21] to target/classes', 'Compiling 1 source file with javac [debug release 21] to target/test-classes', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.530 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0']
  mvn package -Dmaven.test.skip=true(不编译测试也不跑)     1.0 秒

构建缓存扩展

实测 · 本机执行输出
  第一次(存入缓存)clean verify            3.2 秒  ['Attempting to restore project demo:shopapp from build cache', 'Compiling 8 source files with javac [debug release 21] to target/classes', 'Compiling 1 source file with javac [debug release 21] to target/test-classes', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.537 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0', 'Saved Build to local file: <实验目录>']
  本地缓存目录:2 个文件,共 14 KB;顶层 ['v1.1']
  第二次 clean verify(命中缓存)          1.2 秒  ['Attempting to restore project demo:shopapp from build cache', 'Found cached build, restoring demo:shopapp from cache by checksum cac438de9184007e0a70dc3795e022cbb0a1add0499b5f7ba4ccdd31b6e42855']
  命中缓存时被跳过的插件执行: ['resources:resources', 'compiler:compile', 'resources:testResources', 'compiler:testCompile', 'surefire:test', 'jar:jar'] ;日志里出现 Tests run 吗: False
  改 C5.java 之后 clean verify(未命中)    3.2 秒  ['Attempting to restore project demo:shopapp from build cache', 'Compiling 8 source files with javac [debug release 21] to target/classes', 'Compiling 1 source file with javac [debug release 21] to target/test-classes', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.537 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0', 'Saved Build to local file: <实验目录>']
  再来一次 clean verify(新版本已缓存)    1.2 秒  ['Attempting to restore project demo:shopapp from build cache', 'Found cached build, restoring demo:shopapp from cache by checksum 1dc4a5afea92a9b868998c2cf3b703a566dc9f57b02e7c899786d6d4aea1d53c', 'Skipping plugin execution (cached): resources:resources', 'Skipping plugin execution (cached): compiler:compile', 'Skipping plugin execution (cached): resources:testResources', 'Skipping plugin execution (cached): compiler:testCompile']
  同样的命令但 -Dmaven.build.cache.enabled=false    3.2 秒  ['Cache disabled by command line flag, project will be built fully and not cached', 'Compiling 8 source files with javac [debug release 21] to target/classes', 'Compiling 1 source file with javac [debug release 21] to target/test-classes', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.539 s -- in demo.AllTest', 'Tests run: 1, Failures: 0, Errors: 0, Skipped: 0']
  缓存目录现有 4 个文件;其中 buildinfo.xml 个数 2
  buildinfo.xml 里的关键字段: ['hashFunction', 'artifact', 'executions'] ;大小 10519 字符

分步演示

Maven 构建缓存
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12;Apache Maven 3.9.16;maven-compiler-plugin 3.13.0、surefire 3.5.2、jar 3.4.2、maven-build-cache-extension 1.2.0;项目很小(8 个类),绝对时间只对本例有意义;依赖与插件已在本地 ~/.m2
    • 没有验证:Gradle 的 build cache 与增量编译(没有安装)、远程缓存(只用本地目录)、多模块项目里只重建受影响的模块、缓存键里哪些输入(glob、插件版本、环境变量)会改变命中、缓存污染 / 非确定性构建对命中的影响、CI 里的缓存共享
    京ICP备2026067502号-1京公网安备11010502063487号