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
✅ 必要时可通过项目级别配置绕过全局限制
踩过这个坑的朋友应该都懂:环境变量配错,构建全盘皆输。 趁早排查,省心省力。