JDK 21安装后java -version显示旧版本,最常见原因是PATH中旧JDK的bin目录排在前面,系统优先调用旧版java;需用where java(Windows)或which java(macOS/Linux)确认实际路径,并调整PATH顺序或修正JAVA_HOME指向JDK 21根目录。

javac 和 java 命令能正常运行,不代表 JDK 21 已正确安装;很多环境变量配置错误、路径含空格或中文、多版本冲突的问题,都会在编译或运行虚拟线程等新特性时才暴露。
为什么 JDK 21 安装后 java -version 显示旧版本?
最常见原因是 PATH 中旧 JDK 的 bin 目录排在前面,系统优先匹配到老版本的 java。这不是安装失败,而是环境变量顺序问题。
- Windows:用
where java查看实际调用路径,检查系统变量和用户变量中PATH的顺序 - macOS/Linux:运行
which java和echo $PATH,确认/path/to/jdk-21/bin出现在旧路径之前 - IDE(如 IntelliJ)不会自动继承 shell 的
PATH,需在Settings > Build > Gradle/Project SDK中手动指定 JDK 21 路径 - 某些工具(如 Maven wrapper
mvnw)会读取JAVA_HOME,而忽略PATH,务必确保JAVA_HOME指向 JDK 21 根目录(不含bin)
虚拟线程跑不起来?先确认这三件事
虚拟线程(Thread.startVirtualThread())是 JDK 21 正式特性,但依赖 JVM 启动参数和运行时支持。不是写对 API 就能跑通。
- 编译时无需额外参数,但运行时必须使用 JDK 21 的
java命令(而非旧版 JRE) - 若用
java MyApp报错java.lang.UnsupportedOperationException: Virtual threads are not supported,说明当前 JVM 不是 JDK 21 或被降级启动 - Spring Boot 3.1+ 默认启用虚拟线程支持,但需显式配置
spring.threads.virtual.enabled=true;老版本 Spring Boot(如 2.7)完全不识别虚拟线程,会静默退化为平台线程 - 某些安全策略(如自定义
SecurityManager)可能禁用虚拟线程,JDK 21 默认已弃用SecurityManager,建议移除相关配置
JAVA_HOME 设置成 jre 目录就废了
JDK 21 不再自带独立 JRE,整个安装包就是 JDK。把 JAVA_HOME 指向 jre 子目录(比如 C:\Program Files\Java\jdk-21\jre)会导致 javac 找不到、Maven 编译失败、IDE 提示 “No JDK specified”。
- 正确路径示例:
D:\DevTools\JDK\jdk-21(Windows)、/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home(macOS)、/usr/lib/jvm/jdk-21(Linux) - 验证方式:执行
$JAVA_HOME/bin/javac -version,应输出javac 21 - OpenJDK 构建(如 Temurin)解压即用,但 rpm/deb 包安装后路径可能不同(如
/usr/lib/jvm/temurin-21-jdk-amd64),不能假设和 Oracle 官方路径一致
预览特性(如结构化并发)必须加 --enable-preview
像 StructuredTaskScope、StringTemplate 这类处于预览阶段的 API,不是“默认可用”,每次编译和运行都必须显式启用,否则直接报错。
- 编译:
javac --enable-preview --release 21 MyApp.java - 运行:
java --enable-preview MyApp - Maven 项目需在
pom.xml中配置maven-compiler-plugin的compilerArgs和fork,否则 IDE 内编译仍会失败 - 注意:
--enable-preview必须与--release 21配合使用;单独用--enable-preview可能触发不兼容行为
JAVA_HOME 指向错误、以及对预览特性的启用机制缺乏预期——这些细节不体现在安装向导里,却决定你能否真正用上虚拟线程或模式匹配。

















