Java

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

noahkim_ 2024. 12. 19. 23:06

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


1. 참조

참조 타입 정의 및 설명 GC 수집 시점 주요 용도
Strong Reference 코드에서 객체를 직접 가리킴 ❌ 참조가 있는 한 GC 대상 아님 일반 객체 참조
Soft Reference 메모리 부족 시에만 수집되는 참조 ⚠️ 메모리 부족 시 GC 대상 캐시
Weak Reference 강한 참조가 없으면 즉시 수집될 수 있음 ✅ GC 대상 (강한 참조 없을 경우 즉시) 메모리 누수 방지
임시 객체 관리
Phantom Reference 수집된 후에만 감지 가능한 참조.
객체 생명주기 끝을 추적할 때 사용
✅ 객체 수집 후 ReferenceQueue에 등록 정리/리소스 해제 후 처리

 

예시) 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();

 

예시) Phantom Reference

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

System.gc(); // GC 호출
// queue를 통해 팬텀 참조 이벤트 확인 가능
  • 객체가 수집된 후의 이벤트 감지 목적
  • 리소스 해제 작업 및 삭제 후 처리 로적에 사용됨 (참조 목적 X)
  • GC에 의해 수집된 이후에도 참조 가능

 

2. 힙 영역 회수

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

 

알고리즘

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

 

3. 메서드 영역 회수하기

  • JDK 12부터 메서드 영역 회수 공식 지원
항목 내용
회수 대상
- 클래스 정보 (메타데이터)
- 런타임 상수 풀
회수 조건
- 클래스 로더가 GC 대상임
- 해당 클래스의 인스턴스가 모두 GC로 회수됨
- Class 객체/리플렉션 메서드 등 참조 없음
관련 JVM 옵션
- -Xnoclassgc: 클래스 회수 비활성화
- -verbose:class: 클래스 로드 출력
- -Xlog:class+load=info: 로드 로그
- -Xlog:class+unload=info: 언로드 로그
사용 사례
- 리플렉션 기반 바이트코드 생성 라이브러리 사용 시 (e.g. CGLib, Proxy)
- OSGi, JSP, 사용자 정의 ClassLoader 환경 등