前回はStackとQueueを使ったデータ構造の使い方を学びました。
今回は「WeakReference(弱参照)」と「SoftReference(ソフト参照)」について解説します。 Javaのガベージコレクション(GC)の仕組みと合わせて理解することで、メモリを効率よく扱うプログラムが書けるようになります。
参照の種類とGCの基本
Javaはガベージコレクション(GC)という仕組みで、不要になったオブジェクトのメモリを自動的に解放します。「不要」とは「どこからも参照されていない」状態のことです。
Javaの参照には強さのレベルがあります。
強参照(Strong Reference) // 通常の参照。GCで回収されない
ソフト参照(Soft Reference) // メモリ不足のときだけGCで回収される
弱参照(Weak Reference) // 次のGC実行時に回収される
ファントム参照(Phantom Reference) // GC後の後処理に使う(上級者向け)
通常のコードで使う参照はすべて「強参照」です。
String str = "hello"; // 強参照: strが参照している間はGCされない
str = null; // 参照を切るとGC対象になる
WeakReference と SoftReference を使うことで、GCの挙動を制御したキャッシュの実装などができるようになります。
サンプルコード(WeakReferenceの動作)
ファイル作成
「Java40」フォルダに WeakRefTest.java という名前でファイルを作成します

コード入力
以下のコードを入力します。
import java.lang.ref.WeakReference;
public class WeakRefTest {
public static void main(String[] args) throws InterruptedException {
// 強参照
String strong = new String("強参照のオブジェクト");
// 弱参照
WeakReference<String> weak = new WeakReference<>(new String("弱参照のオブジェクト"));
System.out.println("GC前:");
System.out.println("強参照: " + strong);
System.out.println("弱参照: " + weak.get());
// GCを実行する(ヒント: 必ず実行されるとは限らない)
System.gc();
Thread.sleep(100);
System.out.println("\nGC後:");
System.out.println("強参照: " + strong);
System.out.println("弱参照: " + weak.get()); // nullになる可能性がある
// 強参照を切ってからGC
strong = null;
System.gc();
Thread.sleep(100);
System.out.println("\n強参照をnullにしてGC後:");
System.out.println("弱参照: " + weak.get());
}
}

コンパイル
javac WeakRefTest.java

実行
java WeakRefTest
実行結果は次のようになります(GCのタイミングにより異なる場合があります)。
GC前:
強参照: 強参照のオブジェクト
弱参照: 弱参照のオブジェクト
GC後:
強参照: 強参照のオブジェクト
弱参照: null
強参照をnullにしてGC後:
弱参照: null

サンプルコード(WeakHashMapの活用)
WeakHashMap はキーを弱参照で保持するMapです。キーが他から参照されなくなると、GC時にそのエントリが自動的に削除されます。
ファイル作成
「Java40」フォルダに WeakHashMapTest.java という名前でファイルを作成します

コード入力
以下のコードを入力します。
import java.util.WeakHashMap;
import java.util.Map;
public class WeakHashMapTest {
public static void main(String[] args) throws InterruptedException {
Map<String, String> weakMap = new WeakHashMap<>();
// キーを強参照で保持している間はエントリが残る
String key1 = new String("キー1");
String key2 = new String("キー2");
weakMap.put(key1, "値1");
weakMap.put(key2, "値2");
System.out.println("GC前のサイズ: " + weakMap.size());
System.out.println("key1の値: " + weakMap.get(key1));
// key1の強参照を切る
key1 = null;
System.gc();
Thread.sleep(100);
System.out.println("\nkey1をnullにしてGC後:");
System.out.println("サイズ: " + weakMap.size());
System.out.println("key2の値: " + weakMap.get(key2));
// key2の強参照も切る
key2 = null;
System.gc();
Thread.sleep(100);
System.out.println("\nkey2もnullにしてGC後:");
System.out.println("サイズ: " + weakMap.size());
}
}

コンパイル
javac WeakHashMapTest.java

実行
java WeakHashMapTest
実行結果は次のようになります。
GC前のサイズ: 2
key1の値: 値1
key1をnullにしてGC後:
サイズ: 1
key2の値: 値2
key2もnullにしてGC後:
サイズ: 0

SoftReferenceとの違い
SoftReference は WeakReference よりも長く生き残ります。
import java.lang.ref.SoftReference;
SoftReference<String> soft = new SoftReference<>(new String("ソフト参照"));
WeakReference // 次のGC実行時に回収される(すぐ消える)
SoftReference // メモリが不足したときだけ回収される(しばらく残る)
SoftReference はメモリに余裕があるうちはオブジェクトを保持し続けるため、画像や計算結果のキャッシュとして活用できます。メモリが逼迫したときだけGCで回収されるため、OutOfMemoryErrorを防ぎながらキャッシュを使えます。
// SoftReferenceを使ったシンプルなキャッシュの例
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
Map<String, SoftReference<byte[]>> cache = new HashMap<>();
// キャッシュに保存
cache.put("image1", new SoftReference<>(loadImage("image1.png")));
// キャッシュから取得
SoftReference<byte[]> ref = cache.get("image1");
byte[] image = (ref != null) ? ref.get() : null;
if (image == null) {
// GCで回収されていたら再読み込み
image = loadImage("image1.png");
cache.put("image1", new SoftReference<>(image));
}
コードの解説
new WeakReference<>(obj) で弱参照を作成します。weak.get() で参照先のオブジェクトを取得できますが、GCで回収済みの場合は null が返ります。そのため weak.get() の戻り値は必ずnullチェックが必要です。
System.gc() はGCの実行をJVMに「ヒント」として伝えるメソッドですが、必ず実行されるとは保証されていません。実際の本番コードでは System.gc() を明示的に呼ぶことはほとんどなく、JVMが自動的に適切なタイミングでGCを実行します。
WeakHashMap はキーを弱参照で保持するため、キーへの強参照がなくなるとそのエントリ自体がGC時に自動削除されます。セッション管理やキャッシュなど、「キーが使われている間だけ値を保持したい」場面に向いています。
まとめ
通常の参照(強参照)はGCで回収されませんが、WeakReference は次のGC実行時に、SoftReference はメモリ不足時にそれぞれ回収されます。weak.get() や soft.get() で値を取り出す際は必ずnullチェックが必要です。WeakHashMap はキーが参照されなくなると自動的にエントリを削除するMapで、キャッシュやセッション管理に活用できます。これらはやや上級の内容ですが、メモリ効率の高いプログラムを書く際の重要な道具です。
2026/07/31(金) ぱんまる


コメント