ガーベッジコレクション(GC)とは?使い終わったメモリを自動で回収するしくみ

公開: 更新: カテゴリ: テクノロジ系

30秒で結論

ガーベッジコレクションとは(全体像)

GCは、もう使わないメモリを、プログラムに代わって自動で片付けてくれるしくみのこと。手動で「確保したら必ず解放する」のは間違えやすいので、これを自動化して取りこぼしを防ぐ。

身近にたとえると、オフィスの清掃だ。使っている机に印をつけて、印のない机を片付ける(マーク&スイープ)、新入社員のエリアだけ毎日掃除する(世代別)、というように、片付け方にいくつか流派がある。

押さえるのは、GCは便利だが「片付けの間、作業がいったん止まる時間」があること。これをSTW(Stop The World)という。


詳しく:アルゴリズムとSTWだけ覚えれば戦える

ここが記事の心臓部。まず代表的なGCの方法を見ましょう。

代表的なGCの方法

方法考え方特徴
マーク&スイープ使われているものに印 → 印なしを回収基本。すき間(断片化)が出る
コピーGC生きているものを別領域へコピーすき間なし。メモリを2倍使う
世代別GC新しいものはすぐ死ぬ前提で分ける効率がよい。Javaの主流
参照カウント使われている数を数える0で回収。循環参照に弱い

マーク&スイープは、使われているメモリに印をつけ、印のないものを回収する基本の方法です。世代別GCは、「新しいオブジェクトはすぐ使われなくなる」という経験をいかし、新しいものの置き場(Young)を頻繁に、長生きするものの置き場(Old)をたまに片付けて、効率を上げます。

参照カウントは、それぞれのメモリが何か所から使われているかを数え、0になったら回収する方法(Pythonなど)ですが、お互いに参照し合う「循環参照」に弱いという弱点があります。

ここで一番のひっかけが「GCは常に高速で止まらない」という誤解。GCの片付け中はプログラムがいったん止まる時間(STW)があります。最近の並行GC(G1・ZGCなど)でこの止まる時間は大きく短くなりましたが、ゼロではありません。

最後に、GCを使わない言語もあります。

GCを使う言語・使わない言語

区分言語
GCを使うJava・Python・Go・C#など
GCを使わないC・C++(手動)・Rust(所有権で自動管理)

2つめのひっかけが「RustはGCを使う」という誤解。Rustは所有権というしくみで、GCを使わずにメモリを管理します。

わかりやすく言い換えると

要するに、オフィス清掃のたとえで覚えるとラクです。

GCの方法 … マーク&スイープ(印をつけて片付け)、世代別(新しいエリアを頻繁に)、参照カウント(使われている数を数える)

STW … 片付けの間は作業が止まる(常に高速ではない・並行GCで短縮)

RustはGCなし … 所有権でメモリを管理する(GCを使わない)

つまり、「GCにはSTW(止まる時間)がある」「RustはGCを使わない」、この2点が試験の急所です。


試験のツボ

🔴 一番出る:GCとSTW

①GC = 使い終わったメモリを自動で回収(メモリリークを防ぐ)

②STW = 片付け中はプログラムが止まる(常に高速ではない・並行GCで短縮)

🔴 次に出る:代表的な方法

①マーク&スイープ(印をつけて回収)/世代別GC(新しいものはすぐ死ぬ前提)

②参照カウント(使われる数を数える・循環参照に弱い)

🟡 押さえると安定:GCなしの言語

①RustはGCを使わず、所有権でメモリを管理する

②C・C++は手動でメモリを確保・解放する


よくある間違い

「GCは常に高速で、止まる時間はない」→ ✗  GCの片付け中はプログラムが止まる時間(STW)がある。並行GCで短くなるがゼロではない。

「RustはGCを使ってメモリを管理する」→ ✗  Rustは所有権というしくみで、GCを使わずにメモリを管理する。

「参照カウントは循環参照も問題なく回収できる」→ ✗  参照カウントはお互いに参照し合う循環参照に弱く、別のしくみ(サイクル検出など)が必要。


試験での出題パターン

実際の問題でたしかめてみよう。

オリジナル問題1(GCとSTW)

📝 オリジナル問題 1 GCとSTW

ガーベッジコレクションに関する次の記述のうち、正しいものはどれか。

  1. GCは常に高速でいっさい止まらず、片付け中に処理が止まることはないものだとされている
  2. GCは紙に印刷する装置のことで、メモリの回収とは無関係なものだとされているものだ
  3. GCはメモリを必ず増やし続ける機能で、使い終わったメモリは回収しないものだとされている
  4. GCは使い終わったメモリを自動で回収するが、片付け中に止まる時間(STW)がある
テクマスター
テクマスター 解答・解説

解答は 4 ですよ。

GCは使い終わったメモリを自動で回収するしくみですが、片付け中に止まる時間(STW)がありますね。常に高速というわけではありません。

選択肢1の「いっさい止まらない」、選択肢2の「印刷する装置」、選択肢3の「増やし続ける」はどれも誤りですよ。

選択肢判定理由
1止まる時間(STW)がある
2印刷する装置ではない
3使い終わったメモリを回収する
4自動回収だがSTWがある

オリジナル問題2(世代別GC)

📝 オリジナル問題 2 世代別GC

世代別GCに関する次の記述のうち、正しいものはどれか。

  1. 世代別GCは古いオブジェクトほどすぐ死ぬ前提で、古い置き場だけを頻繁に片付ける方式だ
  2. 世代別GCは新しいものはすぐ死ぬ前提で、新しい置き場を頻繁に・古い置き場をたまに片付ける
  3. 世代別GCは紙に印刷する手順のことで、メモリの管理とは無関係なものだとされているのだ
  4. 世代別GCはすべてのオブジェクトを必ず同じ頻度で片付け、世代を分けないものだとされている
テクマスター
テクマスター 解答・解説

解答は 2 ですよ。

世代別GCは新しいものはすぐ死ぬ前提で、新しい置き場(Young)を頻繁に・古い置き場(Old)をたまに片付けますね。効率がよく、Javaの主流です。

選択肢1の「古いものほどすぐ死ぬ」、選択肢3の「印刷する手順」、選択肢4の「同じ頻度」はどれも誤りですよ。

選択肢判定理由
1新しいものほどすぐ死ぬ前提
2新しい置き場を頻繁に片付ける
3印刷する手順ではない
4世代を分けて頻度を変える

オリジナル問題3(GCなしの言語)

📝 オリジナル問題 3 GCなしの言語

GCと言語に関する次の記述のうち、正しいものはどれか。

  1. RustはGCを使わず所有権でメモリ管理し、JavaやPythonはGCを使う言語だ
  2. すべての言語はGCを使ってメモリを管理し、手動で管理する言語はないものだとされている
  3. RustはGCを使う言語で、JavaやPythonはGCを使わない言語だとされている
  4. GCを使うかどうかは紙に印刷する速度で決まり、言語とは無関係なものだとされているのだ
テクマスター
テクマスター 解答・解説

解答は 1 ですよ。

RustはGCを使わず所有権でメモリを管理し、JavaやPythonはGCを使う言語ですね。Rustはコンパイルのときにメモリ管理を保証します。

選択肢2の「すべてGCを使う」、選択肢3のRustとJavaが逆、選択肢4の「印刷する速度」はどれも誤りですよ。

選択肢判定理由
1Rustは所有権・Java/PythonはGC
2手動管理の言語(C・C++)もある
3RustとJava・Pythonが逆
4印刷の速度では決まらない

まとめ

押さえどころ

次に学ぶ


執筆: SikakuQuest編集部

勉強は、クエストになった。

資格の勉強を、冒険に変えるRPG学習アプリ

App Storeで見る