자바의 GC 덕분에 new만 적당히 써도 메모리 관리는 어느 정도 자동으로 돌긴 한다.
하지만 “언제, 어떤 객체를 먼저 수거할지”를 조금 더 미세하게 제어하고 싶을 때가 있다.
이럴 때 쓰는 게 java.lang.ref 패키지의 참조 객체(Reference Object)들이다.
이 네 가지가 “GC 입장에서 얼마나 쉽게 버려도 되는 객체인지”를 등급처럼 나눠 준다.
강한 참조는 우리가 평소에 아무 생각 없이 쓰는 그 참조다.
Object obj = new Object(); // 강한 참조
실무 포인트:
null로 두거나, 스코프 밖으로 흘려 보내야 한다.SoftReference<byte[]> ref = new SoftReference<>(new byte[10 * 1024 * 1024]); // 10MB
byte[] data = ref.get(); // 아직 살아 있으면 참조 가능
예: 이미지 캐시
class ImageCache {
private final Map<String, SoftReference<Image>> cache = new HashMap<>();
public Image get(String key) {
SoftReference<Image> ref = cache.get(key);
Image img = (ref != null) ? ref.get() : null;
if (img == null) {
img = loadImage(key); // 디스크나 네트워크에서 다시 로드
cache.put(key, new SoftReference<>(img));
}
return img;
}
}
WeakReference<Object> ref = new WeakReference<>(new Object());
Object obj = ref.get(); // GC가 수거했으면 여기서 이미 null
대표적인 예가 WeakHashMap이다.
Map<Object, String> map = new WeakHashMap<>();
public void test() {
Object key = new Object();
map.put(key, "value");
System.out.println("before gc: " + map.size()); // 1
key = null; // 강한 참조 제거
System.gc(); // GC 힌트
// 잠깐 대기하여 GC 기회 제공
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
System.out.println("after gc: " + map.size()); // 대부분 0 (엔트리 제거)
}
WeakHashMap은 키를 약한 참조로 들고 있다. 실무 감각:
ReferenceQueue<Resource> queue = new ReferenceQueue<>();
PhantomReference<Resource> phantomRef =
new PhantomReference<>(resource, queue);
phantomRef.get()을 호출해도 항상 null이 나온다. 패턴은 보통 이런 느낌이다.
PhantomReference를 만들어 ReferenceQueue에 등록한다. queue.remove()로 큐를 감시한다. 이게 왜 필요하냐면:
finalize()는 이미 비권장(deprecated)이고, 동작 타이밍이 믿을 수 없다. 실무에서의 현실적인 사용:
| 참조 유형 | GC 수거 시점 | 특징/용도 요약 |
|---|---|---|
| Strong | 참조가 있는 한 절대 수거 안 함 | 평소 우리가 쓰는 일반 참조, OOM의 주범이 되기도 |
| Soft | 메모리가 부족해지면 우선적으로 수거 | 메모리 민감한 캐시, 있으면 좋고 없어도 되는 데이터 |
| Weak | GC가 돌 때마다, 강한 참조 없으면 수거 | WeakHashMap, 자동 엔트리 정리, 메모리 누수 방지 |
| Phantom | 수거 직전 ReferenceQueue로 통지 | 객체 소멸 직전 후처리, finalize 대체 패턴 |
다음 시간엔 WeakHashMap·WeakReference 을 실무에서 사용할 때 어떤걸 고려해야 하는지에 대해 알아보겠다.