0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Javaプログラム実行の仕組み - 超初心者向け完全解説

Last updated at Posted at 2025-08-06

はじめに

Javaプログラムを書き始めたばかりの方にとって、「プログラムがどのように動いているのか」は謎に満ちています。この記事では、Javaプログラムが実行される瞬間から終了するまでの流れを、専門用語を使わずに分かりやすく解説します。

前提知識

この記事を読む前に知っておいてほしいこと:

  • Javaの基本的な文法(クラス、メソッド、変数)
  • コンパイルとは何か(.javaファイルから.classファイルを作ること)

プロセス1: プログラム開始とmainメソッド実行

🏁 何が起こっているの?

あなたがJavaプログラムを実行すると、コンピューターの中で以下のことが起こります:

  1. JVMが起動する
  2. mainメソッドを探して実行する

📖 詳しい説明

Javaプログラムを実行すると、コンピューターの中で「JVM」という特別なソフトウェアが起動します。

JVMって何?

  • JVMは「Java Virtual Machine」の略
  • Javaプログラムを実行するための専用のエンジン
  • あなたのコンピューター上で動く「仮想的なコンピューター」のようなもの

mainメソッドの役割
JVMは必ず最初に「public static void main」というメソッドを探して実行します。これは決まりごとです。

public class HelloWorld {
    public static void main(String[] args) {  // ← ここから実行開始!
        System.out.println("Hello, World!");
    }
}

なぜmainメソッドから始まるの?

  • Javaのプログラムには入り口が必要
  • mainメソッドがその入り口の役割を果たす
  • どんなJavaプログラムでも、mainメソッドが最初に実行されるスタートポイント

🔍 コンピューター内部で実際に起こっていること

上級者向けの技術的詳細:

  1. クラスローディング: JVMがクラスローダーを使って.classファイル(コンパイル済みのJavaコード)を読み込みます
  2. メソッド検証: mainメソッドのシグネチャ(public static void main(String[] args))が正しいかチェック
  3. メモリ割り当て: mainメソッド用のスタックフレームを作成
  4. 実行開始: プログラムカウンターが最初の命令を指して実行開始

プロセス2: 変数の宣言と初期化

🏁 何が起こっているの?

プログラムの中で変数を宣言すると、コンピューターのメモリ(記憶領域)にが用意されます。

📖 詳しい説明

public class CakeShop {
    public static void main(String[] args) {
        int cakeCount = 5;  // ← ここで何が起こる?
        String shopName = "Sweet Dreams";  // ← ここでも何が起こる?
    }
}

変数宣言で起こること

  1. メモリに箱を用意: int cakeCountと書くと、整数を入れるための箱がメモリに作られます
  2. 箱にラベルを貼る: その箱に「cakeCount」というラベル(名前)を付けます
  3. 値を箱に入れる: = 5で、箱の中に「5」という値を入れます

データの種類による違い

  • 基本データ型(int, double, booleanなど): 値そのものが箱に入る
  • 参照データ型(String, 配列、オブジェクト): 実際のデータの住所(参照)が箱に入る
int number = 100;        // 箱の中に「100」が直接入る
String text = "Hello";   // 箱の中に「"Hello"の住所」が入る

🔍 メモリの仕組み

スタック領域

  • mainメソッド内の変数(ローカル変数)はここに作られる
  • メソッドが終了すると自動的に削除される
  • アクセスが高速

ヒープ領域

  • オブジェクト(StringやArrayなど)の実際のデータはここに保存
  • ガベージコレクションによって不要になったら削除される

プロセス3: メソッドの呼び出しと実行

🏁 何が起こっているの?

メソッドを呼び出すと、新しい「作業場」が用意されて、そこで処理が行われます。

📖 詳しい説明

public class Calculator {
    public static void main(String[] args) {
        int result = addNumbers(10, 20);  // ← メソッド呼び出し
        System.out.println(result);
    }
    
    public static int addNumbers(int a, int b) {  // ← 呼び出されるメソッド
        int sum = a + b;
        return sum;
    }
}

メソッド呼び出しのステップ

  1. 新しい作業場を用意: addNumbersメソッド用の新しいスタックフレームを作成
  2. 引数をコピー: 呼び出し元の値(10, 20)を新しい作業場の変数(a, b)にコピー
  3. メソッド内の処理を実行: int sum = a + b;を実行
  4. 結果を返す: return sum;で結果を呼び出し元に返す
  5. 作業場を片付ける: メソッド終了後、スタックフレームを削除

スタックフレームって何?

  • メソッド実行時に作られる「作業場」
  • そのメソッド内で使う変数や情報を保存
  • メソッドが終了すると自動的に削除される

🔍 呼び出しスタックの動作

[main メソッドのスタックフレーム]
├── result変数
└── addNumbers(10, 20)呼び出し
    ↓
    [addNumbers メソッドのスタックフレーム]  ← 新しく作られる
    ├── a = 10
    ├── b = 20
    └── sum = 30
    ↓ return sum
    ↑ 30が返される
[main メソッドのスタックフレーム]
├── result = 30  ← 結果を受け取る

プロセス4: 条件分岐(if文)の処理

🏁 何が起こっているの?

if文では、条件を評価して「true」か「false」かを判断し、実行する処理を選択します。

📖 詳しい説明

public static void checkStock(int stock) {
    if (stock > 0) {        // ← 条件を評価
        System.out.println("在庫があります");
    } else {
        System.out.println("在庫切れです");
    }
}

条件分岐のステップ

  1. 条件式を評価: stock > 0を計算してtrueまたはfalseを得る
  2. 結果に基づいて分岐:
    • trueなら: if文のブロック内を実行
    • falseなら: else文のブロック内を実行(ある場合)

論理演算子の動作

if (age >= 18 && hasLicense) {  // AND演算子
    // 両方がtrueの場合のみ実行
}

if (isWeekend || isHoliday) {   // OR演算子  
    // どちらか一方がtrueなら実行
}

プロセス5: 繰り返し処理(for文)の動作

🏁 何が起こっているの?

for文は「初期化 → 条件チェック → 処理実行 → 更新」のサイクルを繰り返します。

📖 詳しい説明

for (int i = 0; i < 5; i++) {
    System.out.println("回数: " + i);
}

for文の実行順序

  1. 初期化: int i = 0 - カウンター変数iを0で初期化
  2. 条件チェック: i < 5 - 条件がtrueかfalseかをチェック
  3. 処理実行: System.out.println(...) - 条件がtrueなら中身を実行
  4. 更新: i++ - カウンター変数を更新(iを1増加)
  5. 2に戻る: 条件がfalseになるまで繰り返し

実際の動作例「5未満(i < 5)」なので、5は含まれません。

1回目: i=0, 0<5はtrue → 処理実行 → i=1
2回目: i=1, 1<5はtrue → 処理実行 → i=2
3回目: i=2, 2<5はtrue → 処理実行 → i=3
4回目: i=3, 3<5はtrue → 処理実行 → i=4
5回目: i=4, 4<5はtrue → 処理実行 → i=5
6回目: i=5, 5<5はfalse → ループ終了

プロセス6: オブジェクトの生成と操作

🏁 何が起こっているの?

newキーワードを使うと、新しいオブジェクト(データのかたまり)がコンピューターのメモリに作られます。

📖 詳しい説明

まず、基本用語を理解しましょう:

フィールドとは?

  • オブジェクトが持つ「データを入れる箱」のこと
  • 例:ケーキオブジェクトなら「名前」「値段」がフィールド

初期化とは?

  • 箱(フィールド)に最初の値を入れること
  • 例:名前の箱に「チョコレートケーキ」、値段の箱に「1500」を入れる

コンストラクタとは?

  • オブジェクトを作るときに自動で実行される特別なメソッド
  • 箱を作って、最初の値を入れる作業を担当
public class Cake {
    String name;    // フィールド: ケーキ名を入れる箱
    int price;      // フィールド: 値段を入れる箱
    
    public Cake(String name, int price) {  // コンストラクタ
        this.name = name;     // この箱にケーキ名を入れる
        this.price = price;   // この箱に値段を入れる
        System.out.println("👨‍🍳 新しいケーキを作成中: " + name);
    }
}

// メインメソッド内
Cake cake = new Cake("チョコレートケーキ", 1500);

オブジェクト生成の詳細な流れ

Cake cake = new Cake("チョコレートケーキ", 1500); が実行されると、以下の順序で処理が進みます:

  1. 箱の準備: コンピューターがCakeオブジェクト用の箱を用意
  2. コンストラクタ実行: Cake(String name, int price)が自動で呼ばれる
  3. 引数を受け取る: 「チョコレートケーキ」と「1500」がコンストラクタに渡される
  4. this.nameで保存: オブジェクトのname箱に「チョコレートケーキ」を保存
  5. this.priceで保存: オブジェクトのprice箱に「1500」を保存
  6. メッセージ表示: 「👨‍🍳 新しいケーキを作成中: チョコレートケーキ」が画面に表示
  7. 住所を記録: 完成したオブジェクトの場所をcake変数に保存

thisキーワードの役割:

  • 「今作っているこのケーキオブジェクトの」という意味
  • 引数のnameとフィールドのnameを区別するために使う
  • this.nameは「このケーキオブジェクトのname箱」を指す

つまり、new Cake()は「新しいケーキの箱を作って、名前と値段を入れて、その場所を教えて」という指示なのです。

🔍 コンピューター内部で実際に起こっていること

  • ヒープメモリ確保: JVMがCakeオブジェクト用のメモリ空間を割り当て
  • コンストラクタ実行: newによってコンストラクタが自動実行される
  • 参照の返却: オブジェクトのアドレスがスタック変数に格納される

プロセス7: メソッド終了とメモリ解放

🏁 何が起こっているの?

メソッドが終了すると、そのメソッド用のスタックフレームが削除され、使用していたメモリが解放されます。

📖 詳しい説明

ローカル変数の削除
メソッドが終了すると、そのメソッド内で宣言された変数(ローカル変数)は自動的に削除されます。

public static void method() {
    int localVar = 100;  // ローカル変数
    String localStr = "Hello";  // ローカル変数
    
    // メソッド終了時、localVarとlocalStrは自動削除
}

ガベージコレクション
ヒープ領域のオブジェクトは、どの変数からも参照されなくなったときにガベージコレクションによって削除されます。

Student student = new Student("田中", 20);
student = null;  // オブジェクトへの参照を切る
// この時点でStudentオブジェクトはガベージコレクションの対象

プログラム終了時の全体的な流れ

🏁 プログラム終了の瞬間

mainメソッドの最後の行が実行されると、Javaプログラムは終了します。

終了時に起こること

  1. スタック領域のクリア: 全てのスタックフレームが削除
  2. ヒープ領域のクリア: ガベージコレクションが全オブジェクトを削除
  3. JVMの終了: Java仮想マシンが終了
  4. OS制御に戻る: 制御がオペレーティングシステムに戻る

まとめ

Javaプログラムの実行は以下の流れで行われます:

  1. JVM起動 → mainメソッドを探して実行開始
  2. 変数宣言 → メモリに箱を用意して値を保存
  3. メソッド呼び出し → 新しい作業場を作って処理実行
  4. 条件分岐・繰り返し → 条件に基づいて処理の流れを制御
  5. オブジェクト操作 → ヒープ領域にデータを作成・操作
  6. メモリ解放 → 不要になった領域を自動削除
  7. プログラム終了 → 全メモリをクリアしてJVM終了

この流れを理解することで、なぜプログラムが意図した通りに動くのか、なぜエラーが発生するのかが見えてくるはずです。

次のステップ

この記事で基本的な流れを理解したら、次は以下を学習することをお勧めします:

  • デバッガの使い方: プログラムの動作を一行ずつ確認
  • メモリ管理: より詳細なメモリの使い方
  • 例外処理: エラーが発生したときの対処方法
  • マルチスレッド: 複数の処理を並行実行する方法

プログラミングは「コンピューターとの対話」です。コンピューターがあなたのコードをどのように理解し、実行しているかを知ることで、より良いプログラムが書けるようになります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?