根本原因是ide或构建工具(如maven)显式指定了jdk路径,覆盖了系统path中的java.exe;需统一配置ide的project sdk、run configuration的jre及pom.xml中maven-compiler-plugin的source/target版本。

java -version 输出和实际运行时版本不一致
这是最常踩的坑:终端里敲 java -version 显示的是 JDK 17,但你用 IDE 启动 Spring Boot 2.7 项目却报 UnsupportedClassVersionError。根本原因不是环境变量没配好,而是 JVM 启动时没走 PATH 里的 java.exe,而是被 IDE 或构建工具(如 Maven)自己指定的 JAVA_HOME 覆盖了。
实操建议:
- 检查 IDE 的 Project SDK 和 Run Configuration → JRE 设置,两者必须显式指向目标 JDK(比如
C:\Java\jdk1.8.0_412),不能依赖全局JAVA_HOME - Maven 项目要确认
pom.xml中的maven-compiler-plugin的source和target与运行时 JDK 匹配,否则编译出的 class 文件可能在旧 JVM 上跑不起来 - 用
where java(Windows)或which java(Linux/macOS)确认命令行调用的是哪个java.exe,再用java -XshowSettings:properties -version 2>&1 | findstr "java.home"查它实际加载的java.home
同一台机器上多个 Java 进程混用不同 JDK 的风险
表面上看,每个进程各自指定 -Djava.home=... 或通过 JAVA_HOME 启动,就互不影响。但有几个隐藏冲突点:
-
javaw.exe在 Windows 上可能被系统服务或后台工具(如某些监控 agent、杀毒软件插件)静默调用,它们往往硬编码调用注册表里的默认 Java,而不是你当前终端的PATH - 如果两个 JDK 解压目录都在同一父路径下(比如
C:\Java\jdk8和C:\Java\jdk17),而某个脚本错误地用了通配符(如for /d %i in (C:\Java\jdk*) do ...),可能误操作非目标版本 - 部分老工具(如某些 Oracle 客户端、WebLogic 管理控制台)会扫描注册表
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment获取默认 JRE,这个注册表项由 .msi 安装器写入,.zip 解压版不会碰——所以务必只用 .zip 版本,避免注册表污染
CLASSPATH 和模块路径(--module-path)混用导致类加载失败
JDK 8 用 CLASSPATH,JDK 9+ 引入模块系统后,--module-path 和 --add-modules 成了新规则。如果你在 JDK 17 下运行一个依赖 tools.jar(JDK 8 时代常用)的老构建脚本,而该 jar 已在 JDK 17 中被移除或模块化,就会直接 NoClassDefFoundError。
实操建议:
- 彻底弃用全局
CLASSPATH环境变量;现代项目统一用构建工具管理依赖(Maven/Gradle),或启动时用-cp显式传参 - JDK 17+ 若需访问
jdk.compiler模块(替代旧tools.jar),得加参数:--add-modules jdk.compiler --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED - 跨版本调试时,用
jdeps --list-deps扫描 class 文件依赖的 Java 内部 API,提前暴露兼容性问题
临时文件、缓存目录权限和路径长度冲突
OpenJDK 8 默认把 java.io.tmpdir 设为 %TEMP%(通常是 C:\Users\XXX\AppData\Local\Temp),而 JDK 17+ 的 JVM 可能因安全策略更激进,在启动时尝试创建嵌套更深的缓存子目录(如用于 CDS、AOT 编译等)。如果两个版本的 JVM 同时往同一个 tmpdir 写东西,可能因文件锁或权限错乱导致启动失败。
实操建议:
- 为每个 JDK 实例单独指定临时目录:启动命令加
-Djava.io.tmpdir=C:\Java\tmp\jdk8或-Djava.io.tmpdir=C:\Java\tmp\jdk17 - 避免将 JDK 解压到带空格或长路径(如
C:\Program Files\Java\...)的位置;Windows 对 MAX_PATH 限制仍存在,尤其 JDK 17+ 的某些 native 库调用会触发 - 若用批处理切换版本,记得同步清理旧版本残留的
%USERPROFILE%\.jdks(IntelliJ 生成)或%USERPROFILE%\.m2\repository中可能存在的版本相关缓存











