在Java中如何同时管理多个JDK版本_Java多版本环境配置方案

Java多版本共存应使用SDKMAN!工具链隔离而非硬改环境变量,它通过shell hook动态注入临时JAVA_HOME,支持跨平台JDK安装、会话级切换及IDE、Maven、运行配置的独立指定,并需在构建脚本中显式声明版本以避免厂商差异导致的问题。

Java 多版本共存不是靠改系统环境变量硬切,而是用工具链隔离 + 显式声明运行时,否则 JAVA_HOME 冲突、java -versionjavac -version 不一致、Maven 编译失败等问题会反复出现。

SDKMAN! 统一管理 JDK 安装与切换

SDKMAN! 是目前最轻量、跨平台(Linux/macOS/WSL)且对 Java 生态支持最稳的版本管理器,它不修改全局 JAVA_HOME,而是通过 shell hook 注入临时环境变量,每个终端会话可独立指定 JDK。

常见错误:手动下载多个 JDK 解压后硬写 export JAVA_HOME=...~/.bashrc,结果新开终端全乱套,IDE 读不到,CI 脚本也不生效。

  • 安装:
    curl -s "https://get.sdkman.io" | bash
    ,然后重启 shell 或执行 source "$HOME/.sdkman/bin/sdkman-init.sh"

  • 列出可用 JDK:sdk list java(会显示 temurin-17.0.2+8zulu-11.0.22+3 等带厂商和构建号的完整标识)
  • 安装指定版本:sdk install java 17.0.2-temurin(注意用列表里显示的精确 ID,不是简单写 17
  • 设为当前会话默认:sdk use java 17.0.2-temurin;设为全局默认:sdk default java 17.0.2-temurin

在 IDE(IntelliJ IDEA / Eclipse)中绑定项目级 JDK

IDE 不读 SDKMAN! 的 shell 环境,必须显式配置。否则即使终端里 java -version 正确,IDE 编译仍可能用错 JDK 或报 Unsupported class file major version

关键点:项目 SDK ≠ 全局 JDK ≠ Maven JDK ≠ 运行配置 JDK —— 四者要分别确认。

  • IntelliJ:File → Project Structure → Project → Project SDK → 点击 New… → JDK,选 SDKMAN! 安装路径下的具体目录(如 ~/.sdkman/candidates/java/17.0.2-temurin
  • 同时检查 Modules → Language level(决定语法支持,如 record 需要 14+)、Project compiler output path
  • Maven 配置:Settings → Build → Build Tools → Maven → Importing → JDK for importer(影响 pom.xml 解析),以及 Runner → JRE(影响 mvn compile 执行时的 JDK)
  • 运行配置:Edit Configurations → Templates → Application → JRE(控制你点 ▶️ 运行时实际用的 JDK)

在构建脚本中硬编码 JDK 路径或版本标识

CI/CD 流水线或本地自动化脚本若依赖 $JAVA_HOME,而该变量又由 SDKMAN! 动态设置,就容易因 shell 初始化缺失导致 fallback 到系统默认 JDK(比如 macOS 自带的 /usr/bin/java)。

解决方案不是“修环境变量”,而是让构建工具自己找 JDK。

  • Maven:在 pom.xml 中用 maven-compiler-plugin 显式声明源码和目标字节码版本:
    
      org.apache.maven.plugins
      maven-compiler-plugin
      3.11.0
      
        17
        17
      
    
  • Gradle:在 build.gradle 中设置 java.toolchain.version = "17",Gradle 17+ 会自动匹配已安装的 JDK 17
  • Shell 脚本中避免直接调用 java,改用 SDKMAN! 提供的 sdk env 生成临时环境:
    sdk env java 17.0.2-temurin && java -version

最常被忽略的是:不同 JDK 厂商(Temurin、Zulu、Corretto)虽都标称 “JDK 17”,但它们的 java --version 输出格式、内置 JVM 参数默认值、甚至某些 JNI 行为都有差异。线上部署前务必用和生产环境同源的 JDK 构建并验证。