IDEA新项目默认JDK不由JAVA_HOME决定,必须在File→New Projects Settings→Structure for New Projects中显式设置;仅改当前项目Project SDK不影响新项目,若该处为空则IDEA会回退至最早注册的JDK或JBR,导致编译失败。

直接结论:IDEA 的“默认项目 JDK”不是靠系统 JAVA_HOME 决定的,必须在 File → New Projects Settings → Structure for New Projects 中显式设置;只改 Project Structure → Project 只影响当前项目,对新项目完全无效。
为什么新项目还是用旧 JDK?
常见现象是:你刚在当前项目里把 Project SDK 改成 jdk-21,结果新建一个项目时,它又自动选了 jdk-11 或报 “No SDK” 错误。这是因为 IDEA 区分「当前项目」和「未来新项目」两套独立配置,后者由全局默认模板控制。
- 当前项目 SDK 存在
File → Project Structure → Project里,仅作用于打开的这个项目 - 新项目默认值存在
File → New Projects Settings → Structure for New Projects(2021+ 版本路径),它才是真正的“默认” - 如果该页面里
Project SDK是空的或显示None,IDEA 就会 fallback 到最早注册的一个 JDK,甚至可能用 IDE 自带的 JBR(JetBrains Runtime),导致编译失败
怎么正确设置新项目的默认 JDK?
关键动作是先注册、再设为默认,顺序不能错:
- 打开
File → New Projects Settings → Structure for New Projects - 点击左侧
SDKs→ 右上角+→Add JDK→ 选择你本地 OpenJDK 的根目录(例如/usr/lib/jvm/temurin-21-jdk-amd64或C:\Program Files\Eclipse Adoptium\jdk-21.0.1+12-hotspot) - 确认右侧
Classpath列表里能看到rt.jar(旧版)或java.base模块等核心项,才算识别成功 - 回到左侧
Project标签页,在Project SDK下拉框中选中刚添加的 OpenJDK 版本 -
Project language level必须手动匹配(如选21 - Sealed types, pattern matching for switch),不能留空或选低版本 - 点
OK保存 —— 此后所有新建项目都会用这个 JDK
模块 SDK 和 Project SDK 不一致会怎样?
即使你设好了默认 JDK,导入 Maven 多模块项目时仍可能出问题:父模块用了默认 JDK,但某个子模块在 pom.xml 里写了 ,IDEA 会自动把它模块 SDK 强制降级为 JDK 17,而其他模块还是 JDK 21。这会导致:
- 编辑器提示不一致(比如 sealed class 在父模块报错,在子模块不报)
- 运行时类加载失败(
java.lang.UnsupportedClassVersionError) - Gradle 同步后又被覆盖(因为
gradle.properties或settings.gradle里指定了org.gradle.java.home)
解决方法不是硬调模块 SDK,而是统一源头:检查 ~/.gradle/gradle.properties 和项目根目录的 gradle.properties,确保没有冲突的 org.gradle.java.home;Maven 项目则优先以 pom.xml 中的 为准,IDEA 会自动同步 —— 所以改完 pom 后要点右键 → Maven → Reload project。
OpenJDK 路径选错的典型表现
选错路径是最隐蔽也最常踩的坑,尤其在 Linux/macOS 上:
- 选了
/usr/lib/jvm/java-1.21.0-openjdk-amd64/jre(这是 JRE,没javac)→ 添加后Classpath里只有jre/lib/rt.jar,IDEA 会警告 “Not a valid JDK home” - 选了
/usr/lib/jvm/java-1.21.0-openjdk-amd64/bin(到 bin 目录为止)→ IDEA 找不到lib和jmods,直接拒绝添加 - 正确路径必须是包含
bin/javac、lib/tools.jar(旧版)或lib/jdk.jshell.jar(新版)的父目录,即bin的上一级
验证方式很简单:终端进该目录,执行 ./bin/javac -version 能输出版本号,且 ls lib | grep jdk 有内容,就基本没问题。











