«1. Введение

В этом руководстве мы поговорим об исключении, которое выдает Maven при неправильной настройке: JAVA_HOME должен указывать на JDK, а не на JRE.

Maven — мощный инструмент для создания кода. Мы заглянем под капот, чтобы понять, почему возникает эта ошибка, и посмотрим, как ее решить.

2. Проблема JAVA_HOME

После установки Maven мы должны установить переменную среды JAVA_HOME, чтобы инструмент знал, где найти команды JDK для выполнения. Цели Maven запускают соответствующие команды Java для исходного кода проекта.

Например, наиболее распространенным сценарием является компиляция кода путем выполнения команды javac.

Если 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 или JRE

Как Maven проверяет путь JAVA_HOME?

Прежде чем запускать какие-либо цели, Maven проверяет наличие команды java по пути, указанному JAVA_HOME, или запрашивая у ОС установку JDK по умолчанию. Если исполняемый файл не найден, Maven завершает работу с ошибкой.

Вот проверка исполняемого файла mvn для Linux (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

Эта проверка может показаться разумной на первый взгляд, но мы должны учитывать, что и JDK, и JRE имеют папку bin, и обе содержат исполняемый файл Java.

Поэтому можно настроить JAVA_HOME так, чтобы он указывал на установку JRE, скрывая эту конкретную ошибку и вызывая проблемы на более позднем этапе. Хотя основной целью JRE является запуск кода Java, JDK также может выполнять компиляцию и отладку среди других важных отличий.

По этой причине команда компиляции mvn завершится ошибкой, как мы увидим в следующем подразделе.

3.1. Ошибка компиляции из-за JRE вместо JDK

Как обычно с настройками по умолчанию, они очень полезны, если у нас «стандартная» конфигурация.

Например, если мы установим Java 11 в системе Ubuntu 18.04 и не установим переменную среды JAVA_HOME, Maven все равно с радостью найдет наш JDK и будет использовать его для различных целей, включая компиляцию.

Но если нам удалось настроить нестандартную конфигурацию (не говоря уже о том, чтобы навести беспорядок) в нашей системе, полезности Maven уже недостаточно. Это может даже ввести в заблуждение.

Предположим, у нас есть следующая конфигурация в Ubuntu 18.04:

    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"

Давайте посмотрим, что произойдет, если мы попытаемся скомпилировать проект:

mvn clean compile

Теперь мы получим ошибку:

[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. Исправление ошибки компиляции на уровне проекта

Как и во многих других случаях с Maven, рекомендуется установить значимые общесистемные настройки — в этом случае мы изменим значение переменной JAVA_HOME, как описано в разделе 5, чтобы указать на JDK вместо JRE.

Однако, если по какой-либо причине мы не можем установить значения по умолчанию, мы все равно можем переопределить настройки на уровне проекта. Давайте посмотрим, как это сделать.

Сначала мы откроем pom.xml нашего проекта, перейдем в раздел build/pluginManagement/plugins и посмотрим на запись для maven-compiler-plugin:

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

Затем мы добавим к нему конфигурацию, чтобы он использовал пользовательский исполняемый файл и пропустил поиск javac в каталоге JAVA_HOME/bin:

<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>

В системах Unix этот исполняемый файл должен быть сценарием с соответствующими разрешениями. В системах Windows это должен быть файл .exe.

Далее мы попробуем снова скомпилировать проект:

mvn clean compile

Теперь сборка, включая фазу компиляции с плагином maven-compiler-plugin, прошла успешно.

4. Проверка конфигурации JAVA_HOME

Проверить, указывает ли JAVA_HOME на реальный JDK, довольно просто. Мы можем либо распечатать его содержимое в терминале, либо запустить одну из следующих команд оболочки:

4.1. Проверка JAVA_HOME в Linux

Просто откройте терминал и введите:

> $JAVA_HOME/bin/javac -version

Если JAVA_HOME указывает на JDK, вывод должен выглядеть так:

> javac 1.X.0_XX

Если JAVA_HOME не указывает на JDK, ОС выдаст сообщение об ошибке:

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

«

«4.2. Проверка JAVA_HOME в Windows

%JAVA_HOME%\bin\javac -version

Откройте командную строку и введите:

> javac 1.X.0_XX

Если JAVA_HOME указывает на JDK, вывод должен выглядеть так:

> The system cannot find the path specified.

Если JAVA_HOME не указывает на JDK, ОС выдаст сообщение об ошибке:

5. Как решить проблему

    Прежде всего, нам нужно знать, где найти наш JDK:

Если мы установили наш дистрибутив JDK с помощью установщика пакетов , мы должны быть в состоянии найти путь с помощью утилиты поиска ОС. Если дистрибутив был переносимым, давайте проверим папку, в которую мы его распаковали

Как только мы узнаем путь к JDK, мы можем установить нашу переменную среды JAVA_HOME, используя соответствующие результаты для нашей конкретной ОС.

6. Заключение

В этом кратком руководстве мы обсудили ошибку Maven «JAVA_HOME должна указывать на JDK, а не на JRE» и рассмотрели ее основную причину.