はじめに
Java初心者にとって、「Javaプログラムがどのように動いているのか」はとてもイメージしづらいかと思います。この記事では、Javaプログラムの仕組み、実行から終了までの流れをわかりやすく解説していきます。
JVMとは何か?
「JVM」とは、Java仮想マシン(Java Virtual Machine)の略称で、Javaのプログラムが各種コンピューターシステム上で稼働するために必要なソフトウェアです。
「Javaプログラムは一度書けばどこでも動く」と言われている理由は、「Java」がマルチプラットフォーム(Windows、Linux、MacOSなど)で動作する特性を持っており、Javaコードをコンパイルして得られたJavaのモジュール(バイトコード)を読み取り、各プラットフォームが理解できる機械語へ変換し、実行してくれるためです。
つまり、「JVM」は「Java」プログラムがどのOS上でも安定して実行されるための中継役を果たしているのです。いわゆるあなたのコンピュータ上で動く「仮想的なコンピュータ」のようなイメージです。
では、どのような流れでJavaプログラムが実行されていくのかを見ていきましょう。
Javaプログラムが実行される流れ
- Javaソースコード作成
- コンパイル(javac)
- バイトコード(.classファイル)
- JVM(Java Virtual Machine)で実行
- 実行環境(OS & ハードウェア)
一つずつ詳しく解説していきます。
Javaソースコード作成
- テキストエディタを開く
メモ帳、Eclipse、VS Codeなどのテキストエディタを使用します。 - コードを入力する
以下のコードを入力します。これは「Hello World」を表示するシンプルなプログラムです。
public class Hello World {
public static void main (String[] args) {
// "Hello, World!" をコンソールに出力します。
System.out.println("Hello, World!");
}
}
JVMは必ず最初に「public static void main」というメソッドを探して実行します。
どんなJavaプログラムでも、mainメソッドが最初に実行されるスタートポイント。
3. ファイルを保存する
・HelloWorld.javaという名前で保存します。保存する場所はどこでも任意の場所でOKです。(Javaプログラムはこの保存したディレクトリ上でコンパイル~実行することになります)
・ファイル名とクラス名(この場合はHelloWorld)は同じにする必要があります。
テキストファイル(拡張子.java)をJavaコンパイラ(javac)でコンパイルすると、バイトコードに変換され拡張子が.classのバイトコードファイルが生成されます。
生成された.classファイルをJVMで実行することで、プログラムが動くようになります。
コンパイル(javac)
-
コマンドラインを開く
Windowsの場合は「コマンドプロンプト」
MacやLinuxの場合は「ターミナル」 -
保存したディレクトリに移動する
cdコマンドを使って、HelloWorld.javaを保存したディレクトリに移動します。
例:ファイルがデスクトップに保存されている場合「cd Desktop」 -
コンパイルコマンドを入力する
以下のコマンドを入力してコンパイルします。
javac HelloWorld.java
バイトコード(.classファイル)
コンパイルが成功すると、HelloWorld.classというファイルが生成されます。
バイトコードは人間には読みにくいですが、Java仮想マシン(JVM)が理解できる形式です。
また、バイトコードはプラットフォーム非依存のため、Windows、LinuxなどどのOSにおいても、JVMさえあれば同じ.classファイルを実行できます。
JVM(Java Virtual Machine)で実行
以下のコマンドを入力してプログラムを実行します。
java HelloWorld
ここで指定している「HelloWorld」はJavaの「クラス名」です。
クラスを指定してjavaコマンドを実行することで.classファイルが動きます。
JVMは.classファイルのバイトコードを読み込み、コンピュータが直接実行できる機械語に変換して実行します。
実行環境(OS & ハードウェア)
最終的にJVMが変換した機械語はOSを経由してハードウェア上で実行されます。
これにより、プログラムの実行結果が得られます。
(例:コンソールに"Hello, World!"が出力される)
ここまでは、ざっくりとJavaプログラムが実行される流れを解説してきました。
以下では、実際にコンピュータ内部でどのような仕組みが動いているのかを詳しく見ていきます。
JVMのコンポーネント
JVMは以下の主要なコンポーネントで構成されています。
- クラスローダー:Javaクラスファイル(.class)を読み込み、バイトコードをメモリにロードします。
- 実行エンジン:バイトコードを機械語に変換し、命令を実行します。
- メモリ領域:メモリ割り当て、スタック、ヒープ、メソッドエリアなどを含む実行環境を提供します。
- ガーベジコレクタ:いらなくなったゴミを片付ける掃除係のような役割を持ちます。
JVMの理解を深めるためにも、それぞれ詳しく解説していきます。
クラスローダー
プログラムの部品(クラス)を工場に運んでくる係のイメージです。
Javaのソースコードは.classというバイトコードにコンパイルされます。
その.classを見つけてJVMに読み込む役割を担っており、例えるなら「工場の入り口で部品をトラックから降ろす人」をイメージしてもらえると分かりやすいです。
実行エンジン
バイトコードを動かすエンジンとなり、JVMが読み込んだバイトコードを実際に以下2通りの方法にて実行します。
- インタプリタ:1行ずつ読み取って実行(遅いけど準備が簡単)
- JITコンパイラ:よく使う部分をまとめて機械語に変換(速い)
例えるなら「工場の作業員」のような、単純作業はそのままやるけど、何度も出てくる作業は効率化してくれるイメージです。
メモリ領域
プログラムがデータを置く場所(作業スペース)の役割を担っており、主に以下の場所があります。
- ヒープ領域:オブジェクトや配列を置く倉庫
- メソッド領域:クラスやメソッドの情報を置く設計図置き場
- スタック領域:メソッド呼び出しごとの作業机(変数や計算結果を置く)
- PCレジスタ:「次にどの命令を実行するか」を指し示すポインタ
- ネイティブメソッドスタック:Java以外(C言語など)を呼ぶときの机
工場の倉庫や作業机をイメージしてもらえるとわかりやすいかと思います。
ガーベジコレクタ(GC)
使われなくなったオブジェクトを自動で片付けてメモリを空ける役割を担います。
Javaが「メモリ管理を自動でやってくれる」と言われるのはこれのおかげです。
いらなくなったゴミを片付ける掃除係をイメージしてもらえるとわかりやすいです。
JVMコンポーネントまとめ
JVMは、部品を運んできて(クラスローダー)、作業員がそれを動かし(実行エンジン)、机や倉庫を使い(メモリ領域)、最後に掃除係が片付ける(ガーベジコレクタ)という工場のような仕組みです。
このような仕組みを理解しておくことで、よりJavaプログラムの全体像がイメージしやすくなるはずです。少しずつでもいいので頭に入れておきましょう。
おわりに
Javaプログラムの実行は以下の流れで行われます。
- Javaソースコード作成:.javaファイルを任意のディレクトリに保存
- コンパイル(javac):コンパイルコマンドを入力しコンパイルする
- バイトコード(.classファイル):コンパイルが成功すると.classファイルが生成される
- JVM(Java Virtual Machine)で実行:実行コマンドを入力しプログラムを実行する
- 実行環境(OS & ハードウェア):JVMが変換した機械語がOSを経由しプログラムの実行結果が得られる
JVMは以下の主要コンポーネントで構成されています。
- クラスローダー:部品を運ぶ係
- 実行エンジン:作業員(インタプリタ & JIT)
- メモリ領域:倉庫や作業机
- ガーベジコレクタ(GC):掃除係
この記事でJVMの基本的な流れを理解したら、さらにプログラムの流れを細かく深堀していくことで、プログラミング環境での開発や運用がより面白くなるはずです。
JVMの仕組みを理解することで、「Java」以外の言語でもその恩恵が受けられるはずです。JVMの知識が無駄になることはありません。
今回は、初学者向けにわかりやすくポイントを絞って解説させていただきました。伝えきれていないことはまだまだありますので、Javaをマスターしたい方はぜひ深い知識まで積極的に学んでいきましょう。
