Javaのガベージコレクションを徹底解説!初心者でも分かるメモリ管理の仕組み
生徒
「Javaのガベージコレクションって何ですか?どういうときに動くんですか?」
先生
「ガベージコレクションは、Javaが使われなくなったオブジェクトを自動的に削除する仕組みです。プログラム内でオブジェクトが参照されなくなると、メモリを解放してくれるんですよ。具体的なコードで説明していきましょう!」
1. ガベージコレクションの基本
Javaでは、不要になったオブジェクトをメモリから自動的に解放する仕組みがあります。これを「ガベージコレクション」と呼びます。以下のポイントが重要です:
- ガベージコレクションの対象は、どの変数からも参照されなくなったオブジェクトです。
- ガベージコレクションはJVM(Java仮想マシン)によって管理されます。
System.gc()で実行を促せますが、確実に実行されるわけではありません。
2. 参照が外れるタイミング
参照が外れると、そのオブジェクトはどの変数からもアクセスできなくなり、ガベージコレクションの対象になります。以下のコードで確認しましょう。
public class GarbageExample {
public static void main(String[] args) {
Object obj1 = new Object(); // オブジェクト1を生成
Object obj2 = new Object(); // オブジェクト2を生成
obj1 = obj2; // obj1がobj2を参照するように変更
// 最初に生成したオブジェクトは参照が外れる
}
}
上記の例では、obj1がobj2を参照するようになったため、最初に作成されたオブジェクトはどの変数からも参照されなくなり、ガベージコレクションの対象になります。
3. nullを代入して参照を外す
変数にnullを代入することで、参照を外すことができます。以下のコードを見てください:
public class NullExample {
public static void main(String[] args) {
Object obj = new Object(); // オブジェクトを生成
obj = null; // 参照を外す
// 参照が外れたオブジェクトはガベージコレクションの対象となる
}
}
このように、nullを代入することで意図的に参照を外し、不要なオブジェクトをガベージコレクションの対象にすることができます。
4. 試験対策:どのオブジェクトが対象かを判断する
試験でガベージコレクションに関する問題を解く際は、次のポイントに注意してください:
- 変数に
nullを代入することで参照が外れる。 - 変数に別のオブジェクトを代入すると、以前の参照が外れる。
- ガベージコレクションの対象は、どの変数からも参照されなくなったオブジェクト。
以下の例で復習してみましょう:
public class GarbageCollectionTest {
public static void main(String[] args) {
Object obj1 = new Object(); // オブジェクト1を生成
Object obj2 = new Object(); // オブジェクト2を生成
Object obj3 = obj1; // obj3がobj1を参照
obj1 = null; // obj1の参照を外す
obj2 = null; // obj2の参照を外す
// オブジェクト1は参照が残るためガベージコレクションの対象外
// オブジェクト2はどの変数からも参照されていないため対象
}
}
このコードでは、オブジェクト2だけがガベージコレクションの対象になります。
5. ヒープメモリとガベージコレクションの関係
Javaで new 演算子を使って作成されたオブジェクトは、「ヒープ」と呼ばれるメモリ領域に保存されます。ガベージコレクション(GC)はこのヒープ領域を常に監視し、空き容量を確保する役割を担っています。
プログラミング未経験の方でも分かりやすいように、メモリの状態をイメージできるサンプルを用意しました。
public class HeapMemoryExample {
public static void main(String[] args) {
// ヒープ領域に新しい「箱」が作られる
String data = new String("大量のデータ");
// 別の値を代入すると、古い「箱」は誰からも見られなくなる
data = "新しいデータ";
// この時点で「大量のデータ」が入っていた箱は、GCの掃除対象になる
System.out.println(data);
}
}
もしGCがなければ、使わなくなったオブジェクトがヒープ領域を埋め尽くしてしまい、最終的にプログラムが停止(メモリ不足エラー)してしまいます。Javaが自動で掃除をしてくれるおかげで、私たちはメモリ管理を過度に気にせず開発に集中できるのです。
6. System.gc() メソッドの真実
Javaには、プログラマから「今すぐガベージコレクションを実行してほしい」とお願いするための System.gc() というメソッドが存在します。
しかし、このメソッドを呼び出したからといって、すぐに掃除が始まるわけではありません。
public class SystemGcExample {
public static void main(String[] args) {
Object target = new Object();
target = null; // 掃除の対象にする
// JVMに対して「手が空いていたら掃除して」とリクエストする
System.gc();
System.out.println("GCのリクエストを送りました");
}
}
実行結果:
GCのリクエストを送りました
実務や試験での注意点として、System.gc() は「命令」ではなくあくまで「提案」であるということを覚えておきましょう。JVMは独自のアルゴリズムで最適なタイミングを判断するため、基本的にはJVMに任せるのがベストな選択とされています。
7. 到達可能性:島のように孤立したオブジェクト
ガベージコレクションの判定基準として「到達可能性(Reachability)」という考え方があります。これは、プログラムの開始地点から辿って、そのオブジェクトにたどり着けるかどうか、というルールです。
たとえオブジェクト同士が参照し合っていても、変数から切り離されて「孤立した島」のようになると、すべてまとめてGCの対象になります。
class Node {
Node next;
}
public class IslandExample {
public static void main(String[] args) {
Node a = new Node();
Node b = new Node();
a.next = b; // aからbへ参照
b.next = a; // bからaへ参照(相互参照)
a = null; // 変数aからのルートを断つ
b = null; // 変数bからのルートを断つ
// aとbはお互いを見ているが、メインプログラムからは辿れない
// この「孤立した島」はまとめてGCの対象になる
}
}
このように「誰かが参照しているから安心」ではなく、「動いているプログラムから辿り着けるか」が掃除されるかどうかの運命を分けるポイントです。この仕組みを理解すると、メモリ漏れ(メモリーリーク)の少ない綺麗なコードが書けるようになります。
まとめ
この記事では、Javaのガベージコレクションについて詳しく学びました。ガベージコレクションは、使われなくなったオブジェクトを自動的に削除してメモリを解放する仕組みで、プログラマーの負担を軽減します。特に、参照が外れたオブジェクトが対象になるという点が重要です。
また、変数にnullを代入する、または別のオブジェクトを参照させることで、以前のオブジェクトの参照が外れる例も確認しました。以下はその復習のためのサンプルプログラムです:
public class GarbageCollectionSummary {
public static void main(String[] args) {
String data1 = new String("Data1");
String data2 = new String("Data2");
data1 = data2; // data1がdata2を参照するように変更
data2 = null; // data2の参照を外す
// ここで最初の"Data1"オブジェクトはどの変数からも参照されていない
}
}
この例では、最初に生成された"Data1"のオブジェクトがガベージコレクションの対象となります。
以上の内容を理解することで、メモリ管理の基礎をしっかり押さえることができます。ガベージコレクションが行われるタイミングを正確に予測することは難しいですが、どのオブジェクトが対象になるかを理解することは、効率的なプログラム設計につながります。
生徒
「ガベージコレクションが自動でメモリを解放してくれるのは便利ですね!でも、どういうオブジェクトが対象になるのかを間違えないようにしないといけませんね。」
先生
「その通りです。特に変数の参照をしっかり管理することが大切です。不要になったオブジェクトを明示的にnullで参照を外すことも検討すると良いでしょう。」
生徒
「これからコードを書くときに、どの変数がどのオブジェクトを参照しているのかを意識してみます!」
先生
「素晴らしいです!ガベージコレクションを理解することで、メモリ管理がより簡単になりますよ。」