Maven Error “JAVA_HOME should point to a JDK not a JRE” – Maven错误 “JAVA_HOME应指向JDK而非JRE&#8221

最后修改: 2018年 10月 16日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this tutorial, we’re going to talk about an exception that Maven throws when misconfigured: JAVA_HOME should point to a JDK, not a JRE.

在本教程中,我们要讨论的是Maven在配置错误时抛出的一个异常。JAVA_HOME应指向JDK,而不是JRE.

Maven is a powerful tool for building code. We’ll look under the hood to understand why this error happens and will see how to solve it.

Maven是一个构建代码的强大工具。我们将深入了解这个错误发生的原因,并看看如何解决这个问题。

2. The JAVA_HOME Problem

2.JAVA_HOME问题

After installing Maven, we have to set the JAVA_HOME environment variable, so the tool knows where to find the JDK commands to execute. Maven goals run the appropriate Java commands against the project’s source code.

安装Maven后,我们必须设置JAVA_HOME环境变量,以便工具知道在哪里找到要执行的JDK命令。Maven的目标是针对项目的源代码运行适当的Java命令。

For example, the most common scenario is to compile the code by executing the javac command.

例如,最常见的情况是通过执行javac命令来编译代码。

If JAVA_HOME is not pointing to a valid JDK installation, Maven will throw an error at every execution:

如果JAVA_HOME没有指向有效的JDK安装,Maven每次执行都会出现错误。

mvn -version

# Output... 
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 or JRE

3.JDK或JRE

How does Maven verify the JAVA_HOME path?

Maven如何验证JAVA_HOME路径?

Before running any goals, Maven checks for the existence of the java command in the path specified by JAVA_HOME or by asking the OS for a default JDK installation. If the executable is not found, Maven terminates with the error.

在运行任何目标之前,Maven会检查java命令JAVA_HOME指定的路径中是否存在,或者询问操作系统是否有默认的JDK安装。如果找不到可执行文件,Maven就会以错误结束。

Here is the mvn executable check for Linux (Apache Maven v3.5.4):

以下是Linux下的mvn可执行检查(Apache Maven v3.5.4)。

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

This check may seem reasonable at first glance, but we have to consider that both JDK and JRE have a bin folder and both contain an executable java file.

这个检查乍一看似乎很合理,但我们必须考虑到JDK和JRE都有一个bin文件夹,都包含一个可执行的java文件。

Therefore, it’s possible to configure JAVA_HOME to point to a JRE installation, hiding this particular error and causing problems at a later stage. While the JRE’s main purpose is to run Java code, the JDK can also compile and debug among other important differences.

因此,有可能将JAVA_HOME配置为指向JRE安装,从而隐藏了这个特殊的错误,并在后期造成问题。虽然JRE的主要目的是运行Java代码,但JDK也可以编译和调试以及其他重要区别

For this reason, an mvn compile command would fail – as we’ll see in the next subsection.

由于这个原因,mvn编译命令会失败–正如我们将在下一小节看到的。

3.1. Compilation Failure Because of JRE Instead of JDK

3.1.由于使用JRE而不是JDK而导致编译失败

As usual with default settings, they’re very helpful if we have a “standard” configuration.

像通常的默认设置一样,如果我们有一个 “标准 “配置,它们是非常有用的。

For example, if we install Java 11 on an Ubuntu 18.04 system and don’t set the JAVA_HOME environment variable, Maven will still happily find our JDK and use it for the different goals, including compiling.

例如,如果我们在Ubuntu 18.04系统上安装了Java 11,但没有设置JAVA_HOME环境变量,Maven仍然会愉快地找到我们的JDK,并使用它来实现不同的目标,包括编译。

But if we’ve managed to set up a non-standard configuration (let alone made a mess) on our system, Maven’s helpfulness doesn’t suffice anymore. It can be even misleading.

但如果我们设法在系统上设置了非标准的配置(更不用说搞得一团糟),Maven的帮助性就不再足够了。它甚至会产生误导。

Let’s assume we have the following configuration on Ubuntu 18.04:

让我们假设我们在Ubuntu 18.04上有以下配置。

  • JDK 11
  • JRE 8
  • JAVA_HOME set to the path of the JRE 8 installation

If we do our basic check:

如果我们做基本的检查。

mvn --version

We’ll get a meaningful output like this:

我们会得到这样一个有意义的输出。

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"

Let’s see what happens if we try to compile a project:

让我们看看如果我们尝试编译一个项目会发生什么。

mvn clean compile

Now, we get an error:

现在,我们得到一个错误。

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0: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.2. Fixing the Compilation Error on the Project Level

3.2.修复项目层面的编译错误

As in many other cases with Maven, it’s recommended to set up meaningful system-wide settings – in this case, we’ll change the value of the JAVA_HOME variable as described in section 5 to point to the JDK instead of the JRE.

与Maven的许多其他情况一样,建议设置有意义的全系统设置–在本例中,我们将按照第5节所述,改变JAVA_HOME变量的值,以指向JDK而不是JRE。

However, if we can’t set up defaults for whatever reason, we can still override the settings on the project level. Let’s see how to do that.

然而,如果我们由于某种原因无法设置默认值,我们仍然可以在项目层面上覆盖设置。让我们看看如何做到这一点。

First, we’ll open the pom.xml of our project, go to the section build / pluginManagement / plugins and have a look at the entry for the maven-compiler-plugin:

首先,我们打开项目的pom.xml,进入build / pluginManagement / plugins部分,看一下maven-compiler-plugin条目。

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

Then, we’ll add a configuration to it so that it uses a custom executable and skip searching for javac in the JAVA_HOME/bin directory:

然后,我们将给它添加一个配置,使它使用一个自定义的可执行文件,并跳过在JAVA_HOME/bin目录下搜索javac

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

On Unix systems, this executable should be a script with adequate permission. On Windows systems, it should be an .exe file.

在Unix系统上,这个可执行文件应该是一个有足够权限的脚本。在Windows系统上,它应该是一个.exe文件。

Next, we’ll try to compile the project again:

接下来,我们将尝试再次编译该项目。

mvn clean compile

Now, the build – including the compile phase with the maven-compiler-plugin – is successful.

现在,构建(包括使用maven-compiler-plugin的编译阶段)成功了。

4. Checking the JAVA_HOME Configuration

4.检查JAVA_HOME配置

It’s pretty simple to check if JAVA_HOME points to an actual JDK. We can either print its content in a terminal, or we can run one of the following shell commands:

检查JAVA_HOME是否指向一个实际的JDK非常简单。我们可以在终端中打印它的内容,或者运行下面的一个 shell 命令。

4.1. Checking JAVA_HOME on Linux

4.1.在Linux上检查JAVA_HOME

Just open a terminal and type:

只要打开一个终端,然后输入。

> $JAVA_HOME/bin/javac -version

If JAVA_HOME points to a JDK, the output should look like:

如果JAVA_HOME指向一个JDK,输出应该是这样的。

> javac 1.X.0_XX

If JAVA_HOME doesn’t point to a JDK, the OS will throw an error message:

如果JAVA_HOME没有指向一个JDK,操作系统将抛出一个错误信息。

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

4.2. Checking JAVA_HOME on Windows

4.2.在Windows上检查JAVA_HOME

Open a command prompt and type:

打开一个命令提示符并输入。

%JAVA_HOME%\bin\javac -version

If JAVA_HOME points to a JDK, the output should look like:

如果JAVA_HOME指向一个JDK,输出应该是这样的。

> javac 1.X.0_XX

If JAVA_HOME doesn’t point to a JDK, the OS will throw an error message:

如果JAVA_HOME没有指向一个JDK,操作系统将抛出一个错误信息。

> The system cannot find the path specified.

5. How to Solve the Issue

5.如何解决这个问题

First of all, we need to know where to find our JDK:

首先,我们需要知道在哪里可以找到我们的JDK。

  • If we installed our JDK distribution using a package installer, we should be able to find the path using the OS search utility
  • If the distribution was a portable one, let’s check the folder where we extracted it

Once we know the path to the JDK, we can set our JAVA_HOME environment variable, using the appropriate results for our particular OS.

一旦我们知道了JDK的路径,我们就可以设置我们的JAVA_HOME环境变量,使用适合我们特定操作系统的结果

6. Conclusion

6.结论

In this brief tutorial, we’ve discussed the “JAVA_HOME should point to a JDK not a JRE” Maven error and examined its root cause.

在这个简短的教程中,我们讨论了”JAVA_HOME应指向JDK而非JRE”Maven错误,并研究了其根本原因。

Finally, we discussed how to check your JAVA_HOME environment variable, and how to make sure it points to a JDK.

最后,我们讨论了如何检查你的JAVA_HOME环境变量,以及如何确保它指向一个JDK。