SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

Ubuntu ServerにどのJavaを入れるか:17・21・25の選び方と導入手順

Ubuntu 24.04と26.04のサーバーに入れるJavaは、アプリが求めるLTSで決めます。default-jdkの中身の確かめ方、ヘッドレスJDKの導入、2版の切り替えとJAVA_HOMEの設定、日本語の文字化けの確認まで実際のコマンドで説明します。

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, October 17, 2026.

Ubuntu ServerにどのJavaを入れるか

Ubuntu ServerにどのJavaを入れるかは、動かすアプリが要求するバージョンで決めます。サーバーの側で決めるものではありません。2026年10月時点で、Ubuntuのアーカイブには長期サポート版(LTS)のOpenJDK 17、21、25が、24.04と26.04の両方に用意されています。アプリの要求を満たすLTSを選び、openjdk-21-jdk-headless のようにバージョン番号の入ったパッケージ名で入れるのが基本です。

default-jdk という便利なパッケージもあります。ただし、これが指すJavaのバージョンはUbuntuのリリースごとに違います。このあと、その中身を自分のサーバーで確かめる方法、ヘッドレスJDKの導入とスモークテスト、2つのバージョンの切り替え、壊れにくい JAVA_HOME の作り方を順に説明します。JVMのメモリ設定やsystemdでの常駐化はここでは扱いません。

先にアプリの要求バージョンを確認する

Javaのバージョンには下限と上限があります。古すぎるとアプリは起動しません。新しすぎても対応外になることがあります。代表的なアプリについて、各プロジェクトの公式ページの記載をまとめます(2026年10月時点)。

  • Jenkins: Java 21と25をサポートしています。Java 17は「サポート外」の一覧に入っています。Jenkinsのドキュメントは、サポート外のJavaを入れるとコントローラーが起動しないと明記しています。
  • Spring Boot: 公式ドキュメントに載っている4.1.1は、Java 17以上が必要で、Java 26まで対応と書かれています。古い系列のSpring Bootを使っている場合は、その版のドキュメントを確認してください。
  • Apache Tomcat: 11.0.xはJava 17以上、10.1.xは11以上、9.0.xは8以上が必要です。
  • Minecraft Java Editionサーバー: サーバーの版ごとに必要なJavaが違います。使う版について、Mojangの公式ページで確認してください。サーバー全体の手順は VPSでMinecraftサーバーを動かす方法 にあります。

たとえばJenkinsを動かすサーバーに17だけを入れると、Jenkinsは起動しません。原因はJavaのバージョンだけです。だから最初にアプリのドキュメントを開き、「必要なJava」の行を探してください。1台で複数のアプリを動かすなら、全部の条件を満たすバージョンを選ぶか、後半の方法で2つを並べて入れます。Pythonでも考え方は同じで、Ubuntu ServerでどのPythonを使うべきか でも「アプリが決める」を出発点にしています。

default-jdk が何を入れるのかを確かめる

default-jdk と default-jdk-headless は、依存関係を使って実体のOpenJDKを引き込むパッケージです。どのOpenJDKを引き込むかは、サーバー上で次のように確認します。

sudo apt update
apt-cache depends default-jdk-headless
apt-cache policy default-jdk-headless

apt-cache depends の出力で Depends: の行を見てください。そこに出る openjdk-NN-jdk-headless が、このサーバーで default-jdk-headless が実際に入れるJDKです。apt-cache policy の Candidate: は入る予定のバージョンです。その下の行は、パッケージがどのリポジトリから来るかを示します。

参考として、2026年10月時点の packages.ubuntu.com では、24.04(noble)の default-jdk は openjdk-21-jdk に、26.04(resolute)の default-jdk は openjdk-25-jdk に依存しています。default-jdk-headless も同じく21と25です。これはWebサイトの表示であって、あなたのサーバーの答えではありません。判断は、上のコマンドの出力でしてください。

同じパッケージ名で中身が変わるので、default-jdk に頼ると、リリースアップグレードのときにJavaのメジャーバージョンが変わります。アプリが21を前提にしているなら、最初から openjdk-21-jdk-headless と名前で指定したほうが安全です。

ヘッドレスJDKをアーカイブから入れる

VPSには画面がないので、GUI用のライブラリを含まない -headless のパッケージを選びます。JRE(Java実行環境)とJDK(Java開発キット)の違いも確認しておきます。noble の openjdk-21-jre-headless のファイル一覧には bin/java や keytool がありますが、コンパイラの javac はありません。javac はJDKの openjdk-21-jdk-headless に入っています。このパッケージはJREの openjdk-21-jre-headless に依存しているので、JDKを入れればJREも一緒に入ります。

まず、候補があるかを確認します。

apt-cache policy openjdk-17-jdk-headless openjdk-21-jdk-headless openjdk-25-jdk-headless

Candidate: にバージョンが出ていれば、そのCPUアーキテクチャで入れられます。2026年10月時点の packages.ubuntu.com では、24.04の openjdk-25-jdk-headless はamd64とi386向けにしか載っていません。arm64のVPSで24.04を使っているなら、25の候補が出るかを必ず確かめてください。

sudo apt install -y openjdk-21-jdk-headless
java -version
javac -version

java -version の1行目に openjdk と、21で始まるバージョンが出れば成功です。この出力は標準エラーに出ます。そのため、パイプで絞りたいときは java -version 2>&1 | head -n 1 のように 2>&1 を付けます。javac -version でコマンドが見つからないと言われても、それだけでJREしか入っていないとは言い切れません。Bashは $PATH に並んだディレクトリから実行ファイルを探すだけなので、JDKの javac がPATHの外にあっても同じエラーになります。dpkg -l 'openjdk-*-jdk-headless' | grep '^ii' でJDKのパッケージが入っているかを確かめ、入っていれば update-alternatives --list javac で実体のパスを確認してください。

Jenkinsの公式手順は、openjdk-21-jre と fontconfig を入れる形です。Jenkinsを動かすだけならそれで足ります。ここでJDKを選ぶのは、次のスモークテストにコンパイラが必要だからです。

java Hello.java で動作を確かめる

JDK 11から、java コマンドに1つのソースファイルを渡すと、その場でコンパイルして実行できます(JEP 330)。17、21、25のどれでも使えます。コンパイルを行うので、JREだけでは足りず、JDKが必要です。

mkdir -p ~/javatest
cd ~/javatest
cat > Hello.java <<'EOF'
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello from Java " + System.getProperty("java.version"));
        System.out.println("java.home=" + System.getProperty("java.home"));
    }
}
EOF
java Hello.java

Hello from Java 21 で始まる行と、java.home=/usr/lib/jvm/java-21-openjdk- で始まる行が出れば、JDKは正しく動いています。java.home の末尾にはCPUアーキテクチャ名が付きます。amd64なら java-21-openjdk-amd64 です。

2つのバージョンを並べて切り替える(update-alternatives)

Jenkinsは21で、別のツールは25で動かしたい、ということはよくあります。OpenJDKのパッケージは、バージョンごとに /usr/lib/jvm/ の下の別ディレクトリに入ります。そのため、同時に入れても衝突しません。どれを java コマンドとして使うかは、update-alternatives が /usr/bin/java のリンクで決めます。

sudo apt install -y openjdk-25-jdk-headless
update-alternatives --list java
update-alternatives --display java

--list は候補のパスをすべて表示します。--display は、今のモード(auto か manual)と、どのパスが選ばれているかを表示します。

切り替えには、対話式の --config か、スクリプトで使える --set を使います。--set に渡すパスは、上の --list の出力からそのままコピーしてください。ディレクトリ名にアーキテクチャ名が入るので、amd64の例を別のサーバーに貼ると失敗します。

sudo update-alternatives --config java
sudo update-alternatives --set java /usr/lib/jvm/java-25-openjdk-amd64/bin/java
java -version

javac は java とは別のグループです。update-alternatives --list javac で確認し、必要なら同じ手順で切り替えます。java だけを切り替えると、実行は25でコンパイルは21、という状態になります。

覚えておくべき動作が1つあります。グループには自動(auto)と手動(manual)の2つのモードがあります。自動モードでは、パッケージを入れたり消したりするたびに、alternativesの仕組みがリンク先を決め直します。--config や --set で選ぶと手動モードになり、管理者の選択がそのまま保たれます。そのため、後で別のJDKを入れても java の指す先は変わりません。自動に戻すには sudo update-alternatives --auto java を実行します。

1回だけ別のバージョンで動かしたいなら、切り替える必要はありません。--list に出たパスをそのまま実行してください。

MavenやGradle、各種の起動スクリプトは JAVA_HOME 環境変数を見ます。ここに /usr/lib/jvm/java-21-openjdk-amd64 と直接書くと、2つの場面で壊れます。1つはarm64など別のアーキテクチャのサーバーで、ディレクトリ名が違うためです。もう1つは update-alternatives で切り替えたときで、java は25なのに JAVA_HOME は21を指したままになります。

/usr/bin/java は、alternativesのリンクを経由して実体を指すシンボリックリンクです。readlink -f でリンクを最後までたどり、bin/java の2階層上を取れば、今選ばれているJDKのディレクトリになります。

readlink -f "$(which java)"
export JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(which java)")")")"
echo "$JAVA_HOME"
"$JAVA_HOME/bin/java" -version

1行目は、/usr/lib/jvm/java-21-openjdk-amd64/bin/java のような実体のパスを表示します。echo の結果が、そこから /bin/java を除いた部分になっていれば正しい値です。

ログインのたびに設定するには、値ではなく、値を計算する式を ~/.bashrc に書きます。式を書いておけば、切り替えた後に新しいシェルを開くと、自動で新しいJDKを指します。

echo 'export JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(which java)")")")"' >> ~/.bashrc
source ~/.bashrc
echo "$JAVA_HOME"

24.04から26.04へ上げるとJavaはどう変わるか

前に見たとおり、2026年10月時点の default-jdk は、24.04では21を、26.04では25を指しています。default-jdk だけを入れたサーバーを26.04に上げると、アップグレードの途中で25が入ります。alternativesが自動モードなら、どれを java にするかはalternativesの仕組みが決め直します。21にしか対応しないアプリにとって、これは起動しなくなる原因になります。

対策は、アプリが必要とするバージョンを名前で入れておき、アップグレードの後に確かめることです。17、21、25は26.04のアーカイブにもあるので、名前で入れたパッケージはアップグレード後も使い続けられます。

dpkg -l 'openjdk-*' | grep '^ii'
update-alternatives --display java
java -version

--display が意図しないパスを示していたら、前の節の --set で戻します。アップグレード全体の流れは Ubuntu 24.04から26.04へのアップグレード手順 を読んでください。急ぐ必要はありません。Ubuntuの公式リリースサイクルでは、通常のセキュリティ保守の期限は、24.04 LTSが2029年5月、26.04 LTSが2031年5月です。

日本語は文字化けするか:LANG=C と C.UTF-8 で試す

この節は答えではなく、質問として読んでください。ロケールが C の環境でJavaが日本語を出力すると、どうなるでしょうか。結果はJDKのバージョンと、出力先が端末かどうかで変わります。だから自分のサーバーで確かめるのが確実です。

cd ~/javatest
cat > Enc.java <<'EOF'
public class Enc {
    public static void main(String[] args) {
        System.out.println("file.encoding=" + System.getProperty("file.encoding"));
        System.out.println("native.encoding=" + System.getProperty("native.encoding"));
        System.out.println("stdout.encoding=" + System.getProperty("stdout.encoding"));
        System.out.println("日本語");
    }
}
EOF
LC_ALL=C java Enc.java
LC_ALL=C.UTF-8 java Enc.java

LANG ではなく LC_ALL を使っています。シェルに LC_ALL が設定されていると、LANG の指定は無視されるからです。2回の実行で、3つのプロパティの値と 日本語 の行がどう違うかを比べてください。

3つのプロパティの意味は、Javaの公式ドキュメントに書かれています。

  • file.encoding: 標準APIのデフォルト文字コードです。JDK 18で入ったJEP 400により、ロケールに関係なく UTF-8 が既定値になりました。21と25はこちらに当たります。17はJEP 400より前の版なので、ロケールに従います。
  • native.encoding: OSの環境とユーザーの設定から導かれる文字コードです。このプロパティに値を設定しても効果はありません。
  • stdout.encoding: System.out の文字コードです。JDK 21のドキュメントでは、System.out はConsoleがあれば Console.charset() で、なければ stdout.encoding で文字をバイトに変換します。起動時にこの値を UTF-8 に指定することは認められています。JDK 17のドキュメントでは、System.getProperties() の一覧にこのプロパティは載っていません。

大事なのは、file.encoding と stdout.encoding が別物だという点です。file.encoding=UTF-8 と表示されても、それはファイルを読み書きするAPIの話です。端末への出力に使う文字コードは別に決まります。LC_ALL=C の実行で stdout.encoding がUTF-8以外になり、日本語 が ? に置き換わっていれば、原因は出力側の変換です。パイプやファイルにリダイレクトしたときは、Consoleがない状態になるので、結果が変わることもあります。

対処は2つあります。プロセスをUTF-8のロケールで起動するか、java -Dstdout.encoding=UTF-8 Enc.java のように明示的に指定します。今の設定を一覧で見たいときは、java -XshowSettings:properties -version 2>&1 | grep encoding が使えます。ログをファイルに書くアプリが21や25で動いていて、デフォルトの文字コードで書き込んでいるなら、file.encoding がUTF-8なので、ファイルの中身はロケールに左右されません。

Oracle JDKは使うべきか

Oracle JDKのライセンスは、日本の企業でよく話題になります。まず区別しておきます。ここまでの手順で入れたのは、Ubuntuのアーカイブにある openjdk-* パッケージです。OracleのサイトからダウンロードするOracle JDKとは別の配布物です。

Oracle JDKの更新版にどのライセンスが付くかは、Oracleの「Java SE Licensing FAQ」に書かれています。このガイドの執筆時点では、そのFAQのページを開いて確認できませんでした。そのため、期限や条件はここには書きません。Oracle JDKを使う予定があるなら、FAQの最新版を自分で読み、社内のライセンス担当と確認してください。アプリの要件がOracle JDKを名指ししていなければ、アーカイブのOpenJDKを使うことで、この確認作業そのものが不要になります。

Eclipse Temurinを使いたい場合(自分で実行する手順)

どのUbuntuのリリースでも同じ配布元のJDKを使いたい場合は、Eclipse AdoptiumのTemurinが選択肢になります。この節の手順は、上で説明した手順の外にあります。読者が自分の判断で実行するものです。

Adoptiumの公式ページは、鍵を /etc/apt/trusted.gpg.d/ に置く手順を載せています。この場所に置いた鍵は、すべてのリポジトリに対して信頼されます。aptの sources.list(5) は、signed-by で鍵を特定のリポジトリだけに限る方法と、管理者が置く鍵の場所としての /etc/apt/keyrings を案内しています。以下は、公式手順をその形に書き換えたものです。

sudo apt install -y wget gpg
sudo install -d -m 0755 /etc/apt/keyrings
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | sudo tee /etc/apt/keyrings/adoptium.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | sudo tee /etc/apt/sources.list.d/adoptium.list
sudo apt update
apt-cache policy temurin-25-jdk

apt update でこのリポジトリのエラーが出ず、apt-cache policy の Candidate: にバージョンが出れば、そのUbuntuのリリース向けのパッケージがあります。候補が出なくても、それだけでパッケージがないとは決められません。/etc/apt/preferences や /etc/apt/preferences.d/ の設定(apt_preferences)で優先度が0未満になっていると、公開されているバージョンでも入りません。Ubuntuの apt_preferences(5) は、誤った設定でパッケージが入らなくなったり、アップグレードで誤った判断が起きたりすると警告しています。引数なしの apt-cache policy で packages.adoptium.net の行と優先度が出ているかを確かめ、上の2か所の中身も確認してください。それでも候補が出なければ、アーカイブのOpenJDKを使ってください。候補が出たら sudo apt install temurin-25-jdk で入れ、update-alternatives --list java に新しいパスが加わったかを確認します。

signed-by の意味と、古い形式の鍵の置き方で出る警告については、aptのMissing Signed-By通知の意味と直し方 で詳しく説明しています。

FAQ

Ubuntu Serverには default-jdk と openjdk-21-jdk-headless のどちらを入れるべきですか?

アプリが特定のバージョンを要求するなら、openjdk-21-jdk-headless のように番号付きの名前で入れてください。default-jdk が指すバージョンはUbuntuのリリースごとに違います。2026年10月時点の packages.ubuntu.com では、24.04で21、26.04で25です。名前で入れておけば、リリースアップグレードでJavaのメジャーバージョンが勝手に変わりません。今のサーバーでの対応は apt-cache depends default-jdk で確認できます。

java Hello.java が動かないのはなぜですか?

ソースファイルを直接渡す実行方法は、その場でコンパイルを行います。そのため、javac を含むJDKが必要です。openjdk-21-jre-headless のようなJREだけの環境では動きません。javac -version でコマンドが見つからないときは、まず dpkg -l 'openjdk-*-jdk-headless' | grep '^ii' でJDKが入っているかを確かめます。何も出なければ sudo apt install openjdk-21-jdk-headless を実行してください。

JAVA_HOME はどう設定すればいいですか?

/usr/lib/jvm/java-21-openjdk-amd64 のようなパスを直接書くと、arm64のサーバーや、update-alternatives で切り替えた後に、間違った場所を指します。export JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(which java)")")")" を ~/.bashrc に書いてください。今選ばれている java の実体から、JDKのディレクトリを毎回計算します。

LANG=C のサーバーでJavaが日本語を正しく出力しないときは、何を確認すればいいですか?

file.encoding と System.out の文字コードは別に決まります。JDK 18以降、file.encoding はロケールに関係なくUTF-8が既定です。一方、JDK 21の System.out は、Consoleがあれば Console.charset() で、なければ stdout.encoding で変換します。java -XshowSettings:properties -version 2>&1 | grep encoding で値を確認し、UTF-8のロケールで起動するか、-Dstdout.encoding=UTF-8 を付けてください。

Oracle JDKを使わないといけませんか?

アプリの要件がOracle JDKを名指ししていなければ、Ubuntuのアーカイブにある openjdk-* パッケージを使えます。Oracle JDKを使う場合、更新版に付くライセンスは、Oracleの「Java SE Licensing FAQ」に書かれています。使う前にその最新版を自分で読み、社内で確認してください。

#java#openjdk#ubuntu#apt#jdk