Gradle编译阶段必须显式添加--enable-preview,仅设sourceCompatibility="21"或toolchain无效;--release会禁用预览特性,应改用--source/--target并配合--enable-preview;运行和测试阶段也需分别配置jvmArgs="--enable-preview"。

Gradle 编译阶段必须显式加 --enable-preview
只靠 sourceCompatibility = "21" 或 java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } 是不够的——Gradle 不会自动把预览特性开关传给 javac。漏掉这一步,编译直接报错,比如用 record 或字符串模板时提示 “not supported at this language level”。
正确做法是往 compileJava 的 compilerArgs 里明确添加:
-
--enable-preview(必需) - 如果用了
--release,得去掉它——--release会强制禁用所有预览 API,哪怕版本对得上也不行 - 推荐改用
--source 21 --target 21替代--release 21,再配--enable-preview
运行和测试阶段同样要加 --enable-preview
编译过了但一跑就抛 IncompatibleClassChangeError 或 UnsupportedClassVersionError: Preview features are not enabled?这是最常见错误:JVM 运行时没开预览支持。
Gradle 里不同任务类型需分别配置:
立即学习“Java免费学习笔记(深入)”;
tasks.withType<test> { jvmArgs("--enable-preview") }</test>-
tasks.withType<javaexec> { jvmArgs("--enable-preview") }</javaexec>(比如自定义启动任务) - 如果是
application插件,设applicationDefaultJvmArgs = ["--enable-preview"]
注意:IntelliJ IDEA 运行测试时默认不读 Gradle 的 jvmArgs,还得手动在 Run → Edit Configurations → Templates → JUnit → VM Options 里填 --enable-preview。
别被 --add-modules 带偏,预览特性 ≠ 孵化器模块
Java 21 的字符串模板、记录模式这些是预览特性,不是孵化器模块,不需要加 --add-modules。只有像 Java 19/21 的结构化并发(jdk.incubator.concurrent)这类才需要。
混用容易出问题:
- 加了
--add-modules jdk.incubator.foreign但没开--enable-preview→ 编译失败 - 开了
--enable-preview却漏掉--add-modules→ 运行时报NoClassDefFoundError或找不到符号 - Java 21 已将 Foreign Function & Memory API 转正,
jdk.incubator.foreign模块已废弃,继续用会警告甚至失败
验证是否真生效:看 minor version 和运行时输出
光看不报错不等于成功。确认方式有两个:
- 用
javap -v MyClass.class | grep "minor version",结果是65535才表示用了预览编译(JDK 21 的major version是 65,minor version 65535是预览标记) - 运行时加一行
System.out.println(System.getProperty("jdk.version"));,启用后应包含+preview字样(如21.0.1+12-LTS-23不带 preview,而21.0.1+12-LTS-23+preview才对)
最容易被忽略的是:Gradle 配置改了,但 IDE 没刷新缓存,或者本地执行 java -cp . Main 时完全绕过 Gradle —— 此时仍要手动加 --enable-preview,否则照样崩。


















