+7 (920) 556-26-91 пн–пт: 10:00–19:00 (МСК)
Проконсультироваться

Инструкции

Как установить Java 21 и Java 25 на сервер через mise

Канон — Eclipse Temurin 25. Java 21 оставляем для старых проектов. Не путать java@25 без вендора с Temurin.

Как установить Java 21 и Java 25 на сервер через mise

Короткий ответ: на Ubuntu 24.04 ставьте JDK через mise командой mise use -g java@temurin-25 — это Eclipse Temurin 25, канон этой серии. Для проектов, которые ещё на 21, используйте java@temurin-21 и переключайтесь в каталоге проекта. Не пишите java@25: без вендора mise возьмёт OpenJDK, не Temurin. Snap с OpenJDK 26 не ставьте — это не LTS.

Что понадобится

  • Ubuntu 24.04 LTS (noble) с sudo-пользователем — первая настройка VPS;
  • mise с activate, канон установки: mise на Ubuntu 24.04;
  • понимание, какая версия нужна приложению: 25 по умолчанию или 21, если так написано в README;
  • 10–20 минут, отдельный SSH-заход после activate.

Сборки Temurin публикует Adoptium: adoptium.net. mise: mise.jdx.dev. К концу статьи у вас будет глобальный Temurin 25 с javac, рядом — Temurin 21 для старого проекта, понятный JAVA_HOME через activate/exec и шаблон systemd без shims. Игровые лаунчеры и сторонние «сборки под сервер» здесь не разбираются: только Temurin через mise.

Команды копируйте целиком. После каждого критичного шага смотрите java -version и javac -version вместе: расхождение линеек — стоп, не идите писать юнит.

Почему Temurin и почему не java@25

Идентификатор в mise состоит из вендора и линейки. java@temurin-25 — Eclipse Temurin 25, проверенные бинарники Adoptium, javac и java из одной поставки. java@25 без вендора — другой дистрибутив (OpenJDK), другие пути, другой набор пакетов. Для воспроизводимого сервера вендор в команде обязателен. То же для 21: только java@temurin-21, не java@21 «потому что короче».

Источник Что это Когда уместно
mise java@temurin-25 Temurin 25, канон новый сервис, глобальный default
mise java@temurin-21 Temurin 21 проект явно требует 21
mise java@25 OpenJDK без вендора Temurin не использовать в этом гайде
apt openjdk-21 системный JDK Ubuntu можно как системный java, не для жонглирования версиями
snap OpenJDK 26 не LTS не ставить

apt с openjdk-21-jdk на Ubuntu 24.04 — нормальный системный JDK, если вам нужен один java для утилит ОС. Как только появляются два приложения (одно на 21, другое на 25) или нужен предсказуемый JAVA_HOME в systemd — только mise. Snap OpenJDK 26 обходите: линейка не LTS, канал snap живёт отдельно от apt и от mise, в юните получите третий путь.

Шаг 1. mise, если ещё не стоит

curl -fsSL https://mise.run | sh
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc

Новая SSH-сессия, затем:

mise --version
mise doctor

Ожидание: v2026.9.6, doctor без ошибки activate. PPA на 24.04 не нужен.

Шаг 2. Ставим Temurin 25 — канон

mise use -g java@temurin-25
java -version
javac -version
mise which java
echo "$JAVA_HOME"

java -version должен сказать, что это Temurin и линейка 25 (строка Eclipse Temurin / OpenJDK 25). javac -version обязан ответить той же линейкой: если java есть, а javac «command not found», вы поставили JRE-образ или смотрите не ту установку. У Temurin через mise есть и java, и javac.

JAVA_HOME после mise activate указывает на корень той же установки, не на /usr/lib/jvm/java-21-openjdk-amd64. Если переменная пустая — вы не в активированной сессии: заново зайдите по SSH и повторите echo.

Проверка, что это не apt:

readlink -f "$(mise which java)"
type java
dpkg -l 'openjdk-*' 2>/dev/null | grep ^ii || true

Путь — ~/.local/share/mise/installs/java/…, type — shim mise. Наличие пакета openjdk-21 в dpkg само по себе не ошибка, если type java не показывает /usr/bin/java. Если показывает — PATH перебит, смотрите bashrc и новую сессию.

Temurin через mise — это JDK: есть и runtime, и компилятор. Не ищите отдельный пакет «jre» и не ставьте поверх ещё и apt install openjdk-21-jdk «чтобы появился javac». Если javac не находится при живом java — вы не в activate-сессии или which java указывает не туда.

Канон серии — java@temurin-25 глобально. 21 оставляйте для кода, который ещё не собрали под 25. Не прыгайте на 26 через snap «потому что цифра больше»: в этом гайде 26 не LTS и не канон.

Шаг 3. Как переключить 21 и 25

Глобальный default — 25. Проект на 21 не требует сносить 25: поставьте вторую линейку и привяжите её к каталогу.

mise install java@temurin-21
mkdir -p ~/app21
cd ~/app21
mise use java@temurin-21
java -version
mise current

В ~/app21 — Temurin 21. В домашнем каталоге:

cd ~
java -version
mise current

Снова Temurin 25. Файл .tool-versions или mise.toml в ~/app21 фиксирует выбор для любого, кто зайдёт в каталог с activate. Вернуть проект на 25:

cd ~/app21
mise use java@temurin-25
java -version

Разово, не меняя default:

mise exec java@temurin-21 -- java -version
mise exec java@temurin-25 -- javac -version

mise exec не зависит от того, какой java сейчас «текущий». Так удобно гонять тесты на двух JDK в CI-скрипте на том же VPS.

Не переключайте версии симлинком в /usr/lib/jvm и не экспортируйте JAVA_HOME вручную в ~/.profile «навсегда»: вы снова получите рассинхрон с mise. Либо activate, либо exec, либо абсолютный путь в systemd.

Проверка, что в проекте записан вендор, а не голая цифра:

cd ~/app21
cat .tool-versions 2>/dev/null
cat mise.toml 2>/dev/null
grep -R "java" .tool-versions mise.toml 2>/dev/null

В файле должно быть temurin-21 (или temurin-25), не просто 21. Если видите голую цифру — удалите строку и снова mise use java@temurin-21. Иначе соседняя машина без того же default-вендора поставит другой OpenJDK.

Сборку «то на 21, то на 25» в одном и том же WorkingDirectory systemd не смешивайте. Один юнит — одна линейка, путь из mise which java в этом каталоге. Второе приложение — второй юнит и второй абсолютный путь.

JAVA_HOME: activate, exec, systemd

В интерактивном SSH после activate JAVA_HOME уже задан. Проверка:

echo "$JAVA_HOME"
"$JAVA_HOME/bin/java" -version

Для одноразовой команды без смены shell:

mise exec java@temurin-25 -- bash -lc 'echo "$JAVA_HOME"; java -version'

Для systemd — никаких shims и никаких Environment=JAVA_HOME наугад. Сначала:

mise which java
dirname "$(dirname "$(mise which java)")"

Первая команда даёт …/bin/java, вторая — корень JDK, его и ставьте в JAVA_HOME юнита. Пример (пути замените на вывод у себя):

sudo tee /etc/systemd/system/hello-java.service <<'EOF'
[Unit]
Description=hello-java
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/hello-java
ExecStart=/home/deploy/.local/share/mise/installs/java/temurin-25/bin/java -jar /home/deploy/hello-java/app.jar
Environment=JAVA_HOME=/home/deploy/.local/share/mise/installs/java/temurin-25
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

Каталог после installs/java/ на диске может называться иначе, чем в примере: копируйте только то, что печатает mise which java. User= — владелец этой установки. После смены temurin-25 → temurin-21 поправьте обе строки и сделайте daemon-reload.

Проверка юнита, когда jar уже есть:

sudo systemctl daemon-reload
sudo systemctl start hello-java
sudo systemctl status hello-java --no-pager
journalctl -u hello-java -e --no-pager

Пока jar нет, юнит закономерно упадёт — это не ошибка JDK. Для проверки компилятора достаточно javac без systemd:

mkdir -p ~/hello-java
cat > ~/hello-java/Main.java <<'EOF'
public class Main {
  public static void main(String[] args) {
    System.out.println("ok " + Runtime.version());
  }
}
EOF
javac ~/hello-java/Main.java
java -cp ~/hello-java Main

Печать ok и номер 25 (или 21, если вы в каталоге с temurin-21). Этого хватает, чтобы считать JDK рабочим. Если компиляция ругается на class file version — javac новее, чем java, которым запускаете: вы смешали apt и mise либо exec забыли. Запускайте javac и java из одной и той же сессии, без смены каталога между ними.

Порт приложения в этом hello нет: Main только печатает версию. Когда появится HTTP-сервис на 8080, слушайте 127.0.0.1 и не открывайте 8080 в UFW. Снаружи — nginx на 80/443, как в остальных гайдах серии.

Проверка результата

java -version
javac -version
echo "$JAVA_HOME"
mise current
mise ls java
mise which java

Глобально — Temurin 25, javac той же линейки, JAVA_HOME не пустой, which указывает в ~/.local/share/mise/installs/java/. Для 21 — зайти в каталог с mise use java@temurin-21 и повторить java -version.

Частые ошибки

  • java@25 вместо java@temurin-25. Поставите OpenJDK без вендора Adoptium. Всегда указывайте temurin-25 или temurin-21.
  • snap install openjdk. Канал 26 не LTS, путь в /snap, systemd его не знает. Снимите snap, вернитесь к mise.
  • JAVA_HOME из /usr/lib/jvm при java из mise. Утилиты сборки возьмут apt, процесс — Temurin, ошибка «class file version». JAVA_HOME только от той установки, что which java.
  • Shim в ExecStart. Как с Node: только абсолютный путь mise which. Activate в bashrc на юнит не действует.
  • Смешали root и deploy. JAVA_HOME root не существует у User=deploy. Ставьте JDK тем же пользователем.

FAQ

Чем java@temurin-25 отличается от java@25?

temurin-25 — Eclipse Temurin с Adoptium. java@25 без вендора — OpenJDK другого источника. Для сервера фиксируйте вендор, иначе на двух машинах окажутся разные JDK с одним «25» в имени.

Как переключать Java 21 и Java 25 на одном VPS?

Глобально оставьте mise use -g java@temurin-25. В каталоге проекта выполните mise use java@temurin-21 — появится .tool-versions или mise.toml. Разово без смены каталога: mise exec java@temurin-21 с командой java -version.

Можно ли оставить apt openjdk-21 рядом с mise?

Да, как системный JDK Ubuntu. Для приложений и для JAVA_HOME в systemd используйте Temurin из mise, иначе type java и юнит разъедутся. Не добавляйте /usr/lib/jvm в PATH вручную впереди shims.

Почему не snap с OpenJDK 26?

Это не LTS. Канал snap не совпадает ни с apt, ни с mise, путь другой, в юните получите третий java. Канон — Temurin 25 или Temurin 21 через mise.

Как задать JAVA_HOME для systemd?

Не надейтесь на bashrc. Возьмите mise which java, поднимитесь на два уровня от bin/java — это JAVA_HOME. Пропишите Environment=JAVA_HOME=… и ExecStart= абсолютный путь к bin/java. User= юнита — владелец установки mise.

Ещё гайды