1. 简介

在本篇文章中,我们来聊聊 Maven 在配置不当的情况下会抛出的一个经典异常:“JAVA_HOME should point to a JDK not a JRE.”

Maven 是一个强大的项目构建工具。我们会从底层机制入手,分析这个错误的成因,并给出几种常见的解决方案。

2. JAVA_HOME 配置问题

安装完 Maven 后,我们必须正确设置 JAVA_HOME 环境变量,以便 Maven 能找到执行构建任务所需的 JDK 命令(如 javac)。

Maven 的各个目标(goals)会调用 Java 命令对项目源码进行处理,比如最常见的编译操作。

如果 JAVA_HOME 没有指向一个有效的 JDK 安装路径,Maven 在每次执行时都会报错:

mvn -version

# 输出如下...
The JAVA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
NB: JAVA_HOME should point to a JDK not a JRE

3. JDK 与 JRE 的区别

3.1 Maven 是如何校验 JAVA_HOME 的?

在执行任何目标之前,Maven 会检查 JAVA_HOME 所指定路径下是否存在可执行的 java 命令。如果找不到,Maven 就会直接退出并抛出错误。

以下是 Linux 系统下 Maven 3.5.4 版本中的相关检查逻辑(来自 mvn 脚本):

if [ -z "$JAVA_HOME" ] ; then
    JAVACMD=`which java`
else
    JAVACMD="$JAVA_HOME/bin/java"
fi

if [ ! -x "$JAVACMD" ] ; then
    echo "The JAVA_HOME environment variable is not defined correctly" >&2
    echo "This environment variable is needed to run this program" >&2
    echo "NB: JAVA_HOME should point to a JDK not a JRE" >&2
    exit 1
fi

这段检查看起来很合理,但问题在于:JDK 和 JRE 都有 bin 目录,也都包含 java 可执行文件

所以,如果你把 JAVA_HOME 设置成了 JRE 路径,虽然 Maven 不会报这个错误,但会在后续阶段引发更严重的问题

⚠️ 虽然 JRE 可以运行 Java 程序,但只有 JDK 才具备编译、调试等功能。

因此,执行 mvn compile 这类命令时就会失败,我们来看具体场景。

3.2 使用 JRE 导致编译失败

在标准配置下,比如 Ubuntu 18.04 上安装了 JDK 11 并未设置 JAVA_HOME,Maven 通常能自动识别 JDK 并顺利完成编译。

但如果配置混乱,比如:

✅ JDK 11
✅ JRE 8
JAVA_HOME 指向的是 JRE 8 路径

执行:

mvn --version

输出可能如下:

Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-24T18:41:47Z)
Maven home: /opt/apache-maven-3.6.0
Java version: 1.8.0_191, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-42-generic", arch: "amd64", family: "unix"

此时 Maven 能正常运行,但尝试编译项目时:

mvn clean compile

就会报错:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.12.1:compile (default-compile) on project my-app: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?

3.3 项目级别的修复方案

虽然最推荐的做法是全局设置正确的 JAVA_HOME(见第 5 节),但在某些受限环境中,我们可以在项目级别进行覆盖配置

打开项目的 pom.xml,定位到 build/pluginManagement/plugins,找到 maven-compiler-plugin 的配置项:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.12.1</version>
</plugin>

添加如下配置,手动指定 javac 的路径:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.12.1</version>
    <configuration>
        <fork>true</fork>
        <executable>/usr/lib/jvm/java-11-openjdk-amd64/bin/javac</executable>
    </configuration>
</plugin>

✅ Unix 系统中应为脚本文件并具有可执行权限
✅ Windows 系统中应为 .exe 文件

再次执行:

mvn clean compile

此时编译成功,构建完成。

4. 校验 JAVA_HOME 是否指向 JDK

4.1 Linux 系统下的检查方式

打开终端,执行:

$JAVA_HOME/bin/javac -version

✅ 若 JAVA_HOME 正确指向 JDK,输出类似:

javac 1.X.0_XX

❌ 若指向 JRE,则报错:

bash: /bin/javac: No such file or directory

4.2 Windows 系统下的检查方式

打开命令提示符,执行:

%JAVA_HOME%\bin\javac -version

✅ 若 JAVA_HOME 正确指向 JDK,输出类似:

javac 1.X.0_XX

❌ 若指向 JRE,则报错:

The system cannot find the path specified.

5. 如何解决这个问题

解决这个问题的关键是:确保 JAVA_HOME 指向的是 JDK 安装路径,而不是 JRE。

你可以通过以下方式找到 JDK 路径:

  • 如果你通过包管理器安装了 JDK,使用系统搜索功能查找路径
  • 如果是手动解压安装的,检查你解压的目录即可

找到路径后,按照你的操作系统设置环境变量即可,具体方法可参考:Java Home 配置指南

6. 总结

本文我们深入探讨了 Maven 报错 “JAVA_HOME should point to a JDK not a JRE” 的原因,并介绍了几种排查和修复方法。

✅ 确保 JAVA_HOME 指向 JDK
✅ 避免误将 JRE 路径作为 JAVA_HOME
✅ 必要时可通过项目级别配置绕过全局限制

踩过这个坑的朋友应该都懂:环境变量配错,构建全盘皆输。 趁早排查,省心省力。


原始标题:Maven Error “JAVA_HOME should point to a JDK not a JRE” | Baeldung