なぜJavaはどんなOSでも動くのか?JVM・コンパイル・.classファイルの関係をやさしく解説

Java

「Windowsで作ったJavaのプログラムが、なぜMacやLinuxでもそのまま動くの?」――Javaを学び始めると、なんとなく動かしているうちに通り過ぎてしまう疑問です。この記事を読めば、その答えであるJVM(Java仮想マシン)の仕組みがわかります。

あわせて初心者が曖昧なまま進めがちな「.javaと.classの違い」「コンパイルとビルド」「パスとは何か」もスッキリ整理できます。

素朴な疑問:なぜJavaは「どこでも動く」のか

多くの言語では、作ったプログラムは動かすOSごとに作り直しが必要です。たとえばC言語では、コンパイル(プログラムを機械が実行できる形に変換すること)した結果がWindows用・Mac用などOSごとに別物になり、そのままでは他のOSで動きません。

ところがJavaは違い、一度書けばWindowsでもMacでもLinuxでも同じプログラムが動きます。これを「Write Once, Run Anywhere(一度書けば、どこでも動く)」と呼びます。その秘密が「バイトコード」と「JVM」です。


【全体像】Javaが動くまでの流れ

Javaのプログラムが実行されるまでには、大きく3つのステップがあります。

  1. 人が Hello.java(ソースコード)を書く
  2. javac でコンパイルし、Hello.class(バイトコード)を生成する
  3. 各OSにインストールされたJVMがバイトコードを翻訳して実行する

Hello.class はどのOSでも共通のファイルです。Windows用・Mac用・Linux用それぞれのJVMがそのファイルを読み込み、そのOSが理解できる形に翻訳して実行します。JVMがOSの違いを吸収するため、開発者は1つのプログラムを書くだけで済みます。

「どこでも動く」の前提として、実行するOS側にあらかじめJVM(JDKまたはJRE)がインストールされている必要があります。


ステップ1:.javaファイルとは(人が書くソースコード)

エディタやEclipseで書く public class Hello { ... } のようなコードが入ったファイルが .java ファイル(ソースコード)です。人が読み書きするための文章であり、コンピュータはこのままでは実行できません。

以下はもっともシンプルなソースコードの例です。

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

このファイルを Hello.java という名前で保存します。これが「ソースコード」です。


ステップ2:コンパイル(ビルド)で .classファイルに変換する

人が書いた .java をコンピュータ寄りの形に変換する作業がコンパイルです。Javaでは javac というコンパイラが担当し、.java から .class ファイルを作ります。

$ javac Hello.java     # Hello.java → Hello.class が生成される

この .class の中身が「バイトコード」です。人間にはほぼ読めない一方、特定のOSに依存しない「中間的な形」になっているのが最大のポイントです。

コンパイルにまつわる用語を整理しておきましょう。

用語意味
コンパイルソースコード(.java)を実行に向けた形(.class)に変換すること。担当は javac
バイトコードコンパイルで生まれるOSに依存しない中間コード。.class の中身。
ビルドコンパイルを含む「実行できる状態に組み立てる一連の作業」の総称。小さなプログラムではほぼ「コンパイル=ビルド」でOK。

.java.class の違いを表でまとめます。

.javaファイル.classファイル
中身人が書いたソースコードバイトコード(中間コード)
読む相手人間JVM
いつできる自分で書くコンパイルで自動生成
OS依存しない(どのOSでも共通)

Eclipseで javac を打った記憶がないのは、ファイルを保存するたびに裏で自動コンパイルしているからです。「いつのまにか .class ができている」のはこのためです。


ステップ3:JVMがバイトコードを各OS向けに翻訳して実行する

できあがった .class(バイトコード)を実際に動かすのが JVM(Java Virtual Machine=Java仮想マシン) です。JVMは共通のバイトコードを、その時動いているOSが理解できる機械語に翻訳しながら実行します。

$ java Hello     # JVMが起動してバイトコードを実行

ここが「Write Once, Run Anywhere」の核心です。JVMはOSごとに別々のものが用意されています。Windowsには Windows用、Macには Mac用のJVMがあります。だからプログラム(.class)は1つの共通ファイルのままでよく、OSの違いの吸収はJVMが引き受けます。結果、私たちはOSの違いを意識せず1つ書くだけで済みます。

「どこでも動く」とは正確には「JVMさえ入っていれば、どのOSでも同じ .class が動く」という意味です。バイトコード(.class)はそのままではどのOSも直接実行できず、翻訳役のJVMがいて初めて動きます。たとえばWindowsで作った .class を友人のMacで動かすには、そのMacにJVM(JDK/JRE)が必要です。


C言語と比べると違いがはっきりする

C言語との違いを比較すると、JVMの役割がより明確になります。

C言語などJava
コンパイル結果OSごとに異なる実行ファイルOS共通のバイトコード(.class
別OSで動かすにはOSごとに作り直し・再コンパイルが必要そのまま(各OSのJVMが動かす)
OSの違いの吸収開発者が対応JVMが代わりに担う

Javaは「OSごとの違い」をJVMという中間層に肩代わりさせることで、開発者をOSの差異から解放しています。


JDK・JRE・JVMの違いを整理する

この3つは入れ子(包含)の関係にあります。

名称役割こんな人に必要
JVMバイトコードを実行する中核エンジン(単体では使わない)
JREJVM+標準ライブラリ。Javaを「動かす」環境アプリを使うだけの人
JDKJRE+javacなどの開発ツール。Javaを「作る」環境プログラムを書く人(学習者)

学習・開発でインストールするのはJDKです。JDKにはJREもJVMも含まれるため、「JDKを入れれば実行も開発もすべてできます」。Java 11以降はスタンドアロンのJRE単体配布が終了しており、基本的にJDKを入れる形が主流です。学習用はLTS版(執筆時点でJava 25のほか21・17)が安心です。


おまけ:パスとクラスパスとは?

環境構築でよく出てくる「パス」関連の用語も整理しておきます。

  • PATH(パス)javajavac などのコマンドがどのフォルダにあるかをOSに教える設定。通っていないと java: command not found というエラーになります。
  • クラスパス(classpath):JVMが .class や外部ライブラリ(JAR)を探す場所を教える設定。ずれると「クラスが見つからない」エラーの原因になります。

ざっくりまとめると、PATHは「コマンドの置き場所」、クラスパスは「プログラム部品の置き場所」をOSに教えるものです。


例えるなら「共通語の台本」と「各国の通訳」

あなたが書く .java は日本語の脚本です。コンパイルすると世界共通語の台本(=バイトコード/.class)になります。各国の劇場には共通語を現地語に訳す通訳(=JVM)がいます。台本は1つでよく、あとは各劇場の通訳が訳します。だから同じ台本が世界中で上演できます。

C言語は最初から各国語で台本を書くようなものです。上演する国の数だけ書き直しが必要になります。


初心者がつまずきやすいポイント(よくある勘違い)

.classファイルを直接編集すればいい?

いいえ。.class はバイトコードであり、人が編集する形ではありません。修正は必ず .java 側で行い、再コンパイルして新しい .class を作ります。


JREだけ入れれば開発もできる?

できません。JREは「動かす」専用であり javac が含まれていません。ソースコードを書いてコンパイルするにはJDKが必要です。


Windowsで作った.classは本当にそのままMacで動く?

動きます。.class(バイトコード)はOSに依存しないため、Mac側にJVM(JDK/JRE)が入っていれば同じ .class をそのまま実行できます。


まとめ

  • .java(ソースコード)をコンパイルすると .class(バイトコード)になる
  • バイトコードはOSに依存しない共通の形
  • JVMがバイトコードを各OSの機械語に翻訳して実行する(OSごとに専用のJVMがある)
  • だからJavaは「一度書けばどこでも動く」を実現できる
  • 開発で入れるのはJDK(JREもJVMも含まれている)

仕組みがわかったら次は手を動かしてみましょう。複数の .class を1つにまとめて配布・実行する方法はEclipseでJARファイルを作成・実行する方法で解説しています。


参考リソース

コメント

タイトルとURLをコピーしました