必须在根项目统一声明Java工具链,因子模块各自配置sourceCompatibility会导致CI环境JDK不一致、字节码版本冲突引发IncompatibleClassChangeError、AGP 8.x+构建中断;javaToolchains可自动拉起对应JDK,覆盖子模块配置,确保编译一致性。

必须在根项目的 build.gradle(或 build.gradle.kts)中统一声明 Java 工具链,否则子模块各自配置会冲突、CI 构建失败、甚至出现 IncompatibleClassChangeError 这类运行时崩溃。
为什么不能靠子模块各自写 sourceCompatibility
Gradle 多模块项目里,如果每个子模块都单独写 sourceCompatibility = JavaVersion.VERSION_17,表面看没问题,但实际埋了三个雷:
- CI 环境可能因
JAVA_HOME指向旧 JDK(如 JDK 8),导致部分模块编译成功、部分失败,错误信息模糊(比如只报Unsupported class file major version 61) - 子模块之间存在依赖时,A 模块用 JDK 17 编译,B 模块用 JDK 11 编译,字节码版本不一致,JVM 加载时直接抛
IncompatibleClassChangeError - Android Gradle Plugin(AGP)8.x+ 强制要求构建机运行在 JDK 17 上,但若子模块仍设
targetCompatibility = "1.8",Kotlin 插件会检测到compileDebugKotlin和compileDebugJavaWithJavac的 JVM target 不一致而中断构建
推荐做法:用 javaToolchains 统一工具链
Gradle 17+ 默认启用 Toolchain,它比老式 sourceCompatibility 更可靠——它不只声明“想用哪个版本”,而是真正拉起对应 JDK 来执行编译。配置位置必须是根项目的 build.gradle(不是子模块):
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
这个配置会自动作用于所有子模块的 JavaCompile 和 Javadoc 任务。不需要再在各子模块里重复写 sourceCompatibility 或 targetCompatibility,它们会被 Toolchain 覆盖并忽略。
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 如果你还在用 Gradle 7–16,需额外加
sourceCompatibility和targetCompatibility回退兼容,但优先级低于 Toolchain - Android 项目要同步配 AGP 版本:AGP 8.1+ 要求 Gradle 8.0+ + JDK 17,三者缺一不可
- 验证是否生效:运行
./gradlew compileJava --debug | grep "Using Java toolchain",应看到类似Using Java toolchain 'Java 17'的日志
遇到 org.gradle.java.home 冲突怎么办
有些团队会在 gradle.properties 里硬编码 org.gradle.java.home=/opt/jdk-17,这看似统一,实则危险:
- 路径在 CI 容器里不存在,构建直接失败
- 开发者本地没装该路径 JDK,IDE 报红却编译通过(因为用了系统默认 JDK),造成环境不一致
- 升级 JDK 后必须手动改所有
gradle.properties,维护成本高
正确做法是删掉 org.gradle.java.home,完全交给 javaToolchains 自动发现或下载。需要强制指定时,用 org.gradle.jvmargs=-Dorg.gradle.java.installations.auto-download=true 开启自动下载,或在 CI 配置中用 sdkman / asdf 管理 JDK 版本。
Kotlin 模块也要对齐 JVM target
混合 Kotlin/Java 的多模块项目,光配 Java 不够。Kotlin 编译器必须和 Java 工具链生成相同字节码版本,否则构建会报错:
kotlin {
jvmToolchain(17)
}
注意:jvmToolchain(17) 是 Kotlin 插件 1.8+ 的写法,等价于旧版的 kotlinOptions.jvmTarget = "17",但更可靠——它和 Java 的 toolchain 共享同一套 JDK 实例,彻底避免双 target 不一致问题。如果项目还含 Android 模块,android {} 块内无需再设 compileSdk 以外的 Java 相关配置,AGP 会自动继承根项目的 Toolchain。
最容易被忽略的一点:Toolchain 配置只影响编译,不影响运行时。你得确保部署环境(如 Docker 基础镜像、生产服务器 JVM)也装的是同版本 JDK,否则 UnsupportedClassVersionError 会在启动那一刻才炸出来。

















