JREとJDKの違い:JVMの役割とJavaパッケージの選び方

JRE(Java ランタイム環境)はコンパイル済みの Java プログラムを実行します。JDK(Java 開発キット)はランタイム機能に加えてコンパイラと開発ツールを提供するので、Java を学ぶ場合やソースコードを構築する場合は JDK を選択してください。既存のアプリケーションを実行するには、そのアプリケーションのランタイム要件に従います。独自のランタイムをバンドルしているアプリケーションでは、別途 Java をインストールする必要がない場合があります。

JRE とは何ですか?

JREは、コンパイル済みのJavaプログラムを実行するために必要な環境です。JREはJVM(Java仮想マシン)、標準クラスライブラリ、およびサポートランタイムファイルを組み合わせたものです。バイトコードはJVMで使用される命令形式であり、通常Javaソースコードから生成された.classファイルに格納されます。

一般的なランタイム専用のJREパッケージにはjavacソースコンパイラは含まれていません。したがって、javaを実行できることは、開発ツールがインストールされていることの証明にはなりません。また、ランタイム環境の概念と特定のダウンロードサイトで提供されているパッケージ名を区別してください。

JDKとは何ですか?

JDK は Java プログラムの開発および実行のためのツールを提供します。ソースファイルをコンパイルするには javac を使用し、プログラムを実行するには java を使用します。開発用 JDK はすでに実行機能を提供しているため、その JDK でプログラムを実行するだけなら、別の JRE をインストールする必要はありません。

  • javac は .java ソースファイルを .class ファイルにコンパイルします。
  • java は JVM を起動し、Java プログラムを起動します。
  • jar はクラスとリソースを JAR (Java アーカイブ) ファイルにパッケージします。
  • javadoc は宣言とドキュメントコメントから API (アプリケーションプログラミングインターフェース) ドキュメントを生成します。
  • jdb は、実行の停止や変数の検査を含むデバッグをサポートします。

これは、JDK がすべてのエディタや IDE(統合開発環境)を含むという意味ではありません。エディタは別途選択でき、IDE はコードを構築するためにプロジェクト JDK の選択を要求する場合があります。コンパイラの役割は Oracle の javac リファレンス に記載されています。

JVM、JRE、JDK はどのように関連していますか?

JVM はバイトコードを実行するコンポーネントです。JRE はライブラリとサポートファイルを追加してランタイム環境を形成します。JDK は開発ツールを追加しつつ、ランタイム機能も提供します。これらの用語は、異なる役割と範囲を表します。

例えば、javac は HelloWorld.java を HelloWorld.class に変換し、java HelloWorld はプログラムを JVM 上で起動します。クラスファイルは互換性のあるランタイムがあれば別のオペレーティングシステム上でも実行できますが、ネイティブライブラリや特定の Java バージョンを使用するアプリケーションには追加の要件があります。JVM とクラスファイルの関係については、Java 仮想マシン仕様の紹介 を参照してください。

JRE 対 JDK の比較

基準 ランタイム専用 JRE JDK
主な目的 コンパイル済みアプリケーションの実行 アプリケーションの開発、コンパイルおよび実行
JVM とランタイムライブラリ 含まれる 含まれる
java ランチャー 通常利用可能 利用可能
javac コンパイラー 通常は存在しない 利用可能
選択するタイミング アプリケーションが互換性のある外部ランタイムを必要とする場合 Java の学習、ソースコードの作成、または開発作業
ダウンロード可能性 ベンダー、バージョン、オペレーティングシステムによる ベンダーとサポートされているプラットフォームを選択

この表は、ランタイム専用パッケージと開発キットの通常の役割を比較したものです。カスタムランタイムには異なるモジュールの選択が含まれる場合があるため、その名前だけではすべてのライブラリやツールが含まれているとは限りません。

最新のJDKにはJREフォルダが含まれていますか?

「JDKにはJREが含まれる」という表現は、ランタイム機能についての簡略な説明ですが、現在のすべてのディレクトリ構成を正確に説明しているわけではありません。JDK 8以前は内部のjre/ディレクトリを使用していました。JDK 9でモジュラーランタイムイメージが導入されました。OracleはJDK 11以降、JREおよびServer JREの個別ダウンロードの提供を終了しました。Oracle JDK 11 マイグレーションガイドでは、これらのパッケージとレイアウトの変更について説明しています。

すべてのベンダーがランタイム専用パッケージの配布を停止したわけではありません。Eclipse Temurin ダウンロードページでは、JDKとJREパッケージが区別されています。必要なバージョンとオペレーティングシステムに対して実際に利用可能なものを確認してください。あるベンダーによるパッケージングの変更は、Javaの普遍的なルールではありません。

開発者は、JDK の jlinkツール を使用して、必要なモジュールとその依存関係をカスタムランタイムイメージにまとめることもできます。そのようなランタイムをアプリケーションにバンドルすることで、別途インストールされたシステム JRE の必要性を減らすことができます。モジュールの選択と更新は、jlink リファレンスで説明されている通り、配布者の責任のままです。

どのパッケージとバージョンを選ぶべきでしょうか?

  • 学習と開発: コースやプロジェクトで必要なJDKのバージョンを選択してください。ビルドツールやライブラリでサポートされているバージョンも含みます。
  • 既存のアプリケーションの実行: 必要なJavaバージョンや外部ランタイムが必要かどうかをインストール手順で確認してください。システムのJavaを変更しても、バンドル済みランタイムを持つアプリケーションには効果がない場合があります。
  • サーバー展開: 必要なモジュール、オペレーティングシステム、CPUアーキテクチャを一致させてください。ソースコードをビルドしたりJDKツールが必要なサーバーは、JDKが必要になる場合があります。

より大きなバージョン番号であることだけでは互換性が保証されるわけではありません。たとえば、Java 17 のランタイムが必ずしも Java 21 用にコンパイルされたクラスを読み取れるわけではありません。古いアプリケーションを新しい Java で実行する場合も、削除された機能やライブラリの互換性を確認する必要があります。

自身のソースコードについては、以前にサポートされた Java リリースをターゲットにする際に javac --release を考慮してください。これにより、言語機能、プラットフォーム API、およびクラスファイル出力が制限されますが、外部依存関係が自動的に互換性を持つわけではありません。実際のターゲットランタイムで結果をテストしてください。

JDK をインストールし、選択した実行可能ファイルを確認してください

公式のダウンロードページで、パッケージの種類、Javaのバージョン、オペレーティングシステム、CPUアーキテクチャ(x64やARM64など)を選択します。配布元がチェックサムを提供している場合は、インストール前にダウンロードしたファイルをハッシュ値で検証できます。

Windowsへのインストールと確認

Eclipse Temurin MSI インストーラーを使用する場合、Custom Setupでインストールディレクトリや機能を選択します。PATHにJavaを追加するとコマンドラインでの使用が簡単になります; ビルドツールが必要な場合はJAVA_HOME機能を選択します。これらのオプションについては、Temurin Windowsインストールガイドを参照してください。インストール後、既存のターミナルを閉じ、新しいターミナルを開きます。

java -version
javac -version

両方のコマンドが動作し、意図したJavaのメジャーバージョンが表示されることを確認してください。もしjava -versionだけが動作する場合、ランタイムは見つかりましたが、コンパイラが利用できない可能性があります。PowerShellでは、選択されたパスを次のコマンドで確認します:

Get-Command java,javac | Select-Object Name,Source

PATHは、端末が実行可能ファイルを検索する場所のリストです。JAVA_HOMEは、その変数を使用するツールのためのJDKの場所を示します;JDKルートを指すようにしてください、binディレクトリではありません。もし2つの設定が異なるインストールを参照している場合、端末とビルドツールは異なるJavaバージョンを使用する可能性があります。

macOSおよびLinuxの確認

使用しているオペレーティングシステムに合ったパッケージまたはインストーラーを使用してください。実際の手順については、Temurinプラットフォームのインストールガイドを参照してください。インストール後、java -versionおよびjavac -versionを実行します。シェルが解決する内容を確認するには、以下を使用します:

command -v java
command -v javac

結果はシンボリックリンクやバージョンマネージャーの場所である可能性があるため、パスだけからJavaのバージョンを推測しないでください。IDEのプロジェクトJDKやビルド結果も確認してください。古いインストールを削除する前にプロジェクトごとに新しいJDKを選択することで、動作する構成に戻すのが容易になります。

小さな例でコンパイルと実行を確認する

JDKが利用可能な状態で、空の作業ディレクトリを作成し、このソースをHelloWorld.javaとして保存します。ファイル名の大文字・小文字はクラス名に合わせ、エディタが.txtという拡張子を追加していないことを確認してください。例ではパッケージ宣言や外部ライブラリは使用していません。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

ファイルがあるディレクトリでターミナルを開き、次のコマンドを順番に実行します:

javac HelloWorld.java
java -cp . HelloWorld

最初のコマンドはクラスファイルを作成します。2番目は現在のディレクトリ(.)でHelloWorldクラスを検索して実行します。クラス名に.classを追加しないでください。予想される出力は次の通りです:

Hello, Java!

JDK 11以降では、java HelloWorld.javaを使ってソースファイルを直接起動することもできます。これは内部的にコンパイルを行うため、ランチャーの名前がランタイム専用のJREでも同じ操作ができることを意味するわけではありません。二段階の例では、ソースとクラスの違いを確認できます。条件については、ソースファイル実行に関するjavaリファレンスを参照してください。

コンパイル済みクラスを実行可能なJARにパッケージするには、HelloWorld.classが作成された後、同じディレクトリで次のコマンドを実行します。

jar --create --file hello.jar --main-class HelloWorld HelloWorld.class
java -jar hello.jar

アーカイブの作成には開発ツールが必要です。完成したJARの実行には互換性のあるランタイムが必要です。他のアプリケーションでは追加のライブラリや起動オプションが必要な場合があります。アーカイブ作成のオプションについては、jarコマンドリファレンスを参照してください。

一般的なインストールおよび起動の問題をトラブルシュートする

症状 確認すべきこと 対処方法
java または javac が見つからない 実行可能ファイルは存在し、PATH に対象の JDK の bin ディレクトリが含まれている 新しいターミナルを開き、実行可能ファイルをフルパスで確認する
java は動作するが、javac は動作しない ランタイム専用のパッケージ、または実行可能パスが混在している 開発用 JDK をインストールするか、既存の JDK のパスを選択する
UnsupportedClassVersionError ランタイムがクラスファイルのバージョンに対応しているか 互換性のあるランタイムを使用してください。必要に応じてターゲットリリース用に自分のコードを再ビルドしてください
Could not find or load main class クラス名、作業ディレクトリ、およびクラスパス この例では、HelloWorld.class を含むディレクトリで java -cp . HelloWorld を実行します
IDEでは動作するが、ターミナルでは失敗する プロジェクトの JDK とターミナルの java および javac IDE、PATH、JAVA_HOME、およびビルドツールの JDK 選択を個別に確認してください

障害を診断する際は、まず実際にどの実行ファイルが動作しているかを確認してください。パスとバージョンが正しく、小さな例が動作することを確認したら、アプリケーションの依存関係や起動オプションを調査します。