Java/JVM

[JVM 밑바닥까지 파헤치기] 3-1. 가비지 컬렉터와 메모리 할당 전략: 회수

noahkim_ 2024. 12. 19. 23:06

저우즈밍 님의 "JVM 밑바닥까지 파헤치기" 책을 정리한 포스팅 입니다.


1. 참조

  • 힙에 있는 객체의 메모리 주소를 가리키는 값
  • ✅ GC는 참조 그래프를 따라 GC Root로부터 도달 가능한지를 기준으로 객체의 생존 여부를 결정함

 

타입

참조 타입 정의 및 설명 GC 수집 시점 주요 용도
Strong Reference 일반적인 객체 참조 일반 객체 참조
Soft Reference 메모리 부족 시에만 수집되는 참조 ⚠️ 메모리 부족 시 캐시
Weak Reference 강한 참조가 사라지면, 다음 GC에 바로 수거 대상이 되는 참조 메모리 누수 방지
Phantom Reference 객체가 완전히 GC 대상이 된 후 감지하기 위한 참조 객체 이벤트 감지

 

예시) Soft Reference

더보기
SoftReference<String> softRef = new SoftReference<>(strongRef);

 

 

예시) Weak Reference

더보기
String strong = new String("I am strong");
WeakReference<String> weakRef = new WeakReference<>(strong);

strong = null;
System.gc();

 

WeakHashMap

Map<Object, String> map = new WeakHashMap<>();

Object key = new Object();
map.put(key, "value");

key = null;
System.gc();

System.out.println(map.size()); 
// 0 이 될 수 있음
  • 일반 HashMap은 외부에서 key의 strong reference가 해제되어도 Map 내부에서 strong reference로 보관
  • ⚠️ 관련 객체가 GC에 의해 수거되지 않음
  • ➡️ key를 WeakReference로 보관하므로 외부 strong reference가 해제되면 key와 entry가 GC에 의해 수거됨

 

예시) Phantom Reference

더보기
ReferenceQueue<String> queue = new ReferenceQueue<>();
PhantomReference<String> phantomRef = new PhantomReference<>(new String("I am phantom"), queue);

System.gc(); // GC 호출
// queue를 통해 팬텀 참조 이벤트 확인 가능
  • GC가 객체를 실제 메모리에서 제거하기 직전에 ReferenceQueue에 Phantom Reference를 넣어줌
  • ⚠️ get() 불가 (항상 null값)
  • ✅ 리소스 해제 작업 및 삭제 후 처리 로직에 사용됨

 

2. 힙 영역 회수

  • 메모리 회수가 동적으로 이루어짐
  • ✅ 힙을 청소하려면, 어떤 객체가 살아있고 죽어있는지 판단해야 함

 

알고리즘

항목 참조 카운팅 알고리즘
도달 가능성 분석 알고리즘
기본 원리 객체의 참조 카운터에 따라 살아있는지 판단
GC Root에서 객체 참조 그래프를 따라가며 도달 여부 판단
로직 참조 시 +1, 참조 해제 시 -1, 카운터가 0이면 수집
GC Root와 연결되지 않은 객체는 수집 대상
문제점/제약 순환 참조 시 수집 불가
순환 참조도 안전하게 수집 가능
부가 처리 없음
finalize() 호출 대상은 F-Queue에 넣고 나중에 처리
객체 부활 가능성 불가능
finalize() 중 객체가 참조를 다시 얻으면 1회 부활 허용
사용 예 Objective-C, 일부 C++ 스마트 포인터 등
JVM 기반 언어 (Java, Kotlin 등)

 

3. 메서드 영역 회수

  • JDK 12부터 메서드 영역 회수 공식 지원
  • ✅ ex) 리플렉션 기반 바이트코드 생성 라이브러리 (CGLib, Proxy)
  • ✅ ex) OSGi, JSP, 사용자 정의 ClassLoader 환경 등

 

회수 조건

  • 해당 클래스의 클래스 로더가 GC됨
  • 해당 클래스의 모든 인스턴스가 GC됨
  • Class 객체/리플렉션 메서드에 대한 참조 없음

 

JVM 옵션

옵션 설명
-Xnoclassgc 클래스 언로딩 비활성화
-verbose:class 클래스 로드 로그 출력
-Xlog:class+load=info 클래스 로드 로그
-Xlog:class+unload=info 클래스 언로드 로그