힙 객체 참조 유형
GC Root에서 시작하여 참조 체인을 따라가며 도달 가능 여부를 판단하며, Java에는 4가지 참조 유형이 있습니다.
GC Root 종류
1. 스택(Stack) 지역 변수
- 현재 실행 중인 메서드의 지역 변수
- 매개변수
2. 정적(static) 변수
- 클래스 로딩 시 메서드 영역에 저장
3. JNI 참조
- 네이티브 코드에서 참조하는 객체
4. 활성 스레드
- 실행 중인 스레드 객체 자체
힙 객체 참조 4가지 유형
1. Strong Reference (강한 참조)
Object obj = new Object(); // 일반적인 참조
// GC Root에서 도달 가능한 한 절대 수거 안됨
// obj = null 해야 수거 대상이 됨
특징: 메모리 부족해도 절대 수거 안함 → OOM 발생 가능
2. Soft Reference (부드러운 참조)
SoftReference<Object> softRef = new SoftReference<>(new Object());
Object obj = softRef.get(); // null일 수 있음
특징: 메모리가 부족할 때만 수거
→ 메모리 여유 있으면 유지 O
→ 메모리 부족하면 수거
→ 캐시 구현에 적합
3. Weak Reference (약한 참조)
WeakReference<Object> weakRef = new WeakReference<>(new Object());
Object obj = weakRef.get(); // null일 수 있음
특징: GC 실행 시 무조건 수거
→ Strong Reference가 없으면 다음 GC에서 바로 수거
→ WeakHashMap에서 활용
4. Phantom Reference (유령 참조)
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef =
new PhantomReference<>(new Object(), queue);
phantomRef.get(); // 항상 null 반환
특징: 객체가 수거된 후 ReferenceQueue에 등록
→ 객체 소멸 시점 감지용
→ 직접 객체 접근 불가
→ 리소스 정리 작업에 활용
참조 강도 비교
| 참조 유형 | 수거 시점 | 용도 |
|---|---|---|
| Strong | 참조 해제 시 | 일반적인 사용 |
| Soft | 메모리 부족 시 | 캐시 |
| Weak | 다음 GC 실행 시 | WeakHashMap |
| Phantom | 수거 완료 후 | 리소스 정리 |
Reachability 판단 흐름
GC Root
├── Strong → 객체A O (절대 수거 안함)
│ └── Strong → 객체B O
├── Soft → 객체C (메모리 부족 시 수거)
├── Weak → 객체D (GC 시 바로 수거)
└── (끊김)
객체E (Unreachable, 바로 수거)
실사용 예시
// Soft Reference - 캐시
Map<Key, SoftReference<Value>> cache = new HashMap<>();
cache.put(key, new SoftReference<>(heavyObject));
// 메모리 부족 시 자동으로 캐시 비워짐 O
// Weak Reference - WeakHashMap
Map<Key, Value> map = new WeakHashMap<>();
// Key 객체에 Strong Reference가 없어지면
// 해당 엔트리 자동 제거 O
일반적으로는 Strong Reference만 사용하지만, 캐시나 메모리 민감한 자료구조를 구현할 때 Soft/Weak Reference를 활용하면 GC와 협력하여 메모리를 효율적으로 관리할 수 있습니다.