Java

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

noahkim_ 2024. 12. 19. 23:06

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


1. 참조

Strong Reference

  • 프로그램 코드에서 할당된 참조
  • 특정 객체에 강한 참조 관계가 하나라도 존재한다면, 해당 객체는 GC의 대상이 되지 않음

 

Soft Reference

SoftReference<String> softRef = new SoftReference<>(strongRef);
  • 메모리가 부족할 경우에만 GC의 대상이 되는 참조
  • 캐싱 시스템

 

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. 힙 영역 회수

  • 메모리 회수가 동적으로 이루어짐
    • 인스턴스는 동적으로 생성되므로 그때마다 메모리 요구량이 달라짐
  • 힙을 청소하려면, 어떤 객체가 살아있고 죽어있는지 판단해야 함
    • 프로세스에서 사용될 수 있는지의 여부

 

참조 카운팅 알고리즘

로직
  • 객체를 가리키는 참조 카운터 필드 추가
  • 참조하는 곳이 늘어날 때마다 1씩 증가, 줄어들 때마다 1씩 감소
  • 카운터 값이 0이 되면 메모리 회수

 

특징
  • 자바에서 사용 X
  • 순환 참조 문제 발생
    • 서로를 참조하는 객체가 더이상 사용되지 않더라도, 참조 카운트는 1 이상으로 유지됨

 

도달 가능성 분석 알고리즘

  • GC 루트를 시작으로 트리를 탐색

 

marking
  • 도달 불가능한 객체
    • 어떤 객체와 GC 루트 사이의 참조 체인이 없는 경우
    • 더 이상 사용 불가
  • finalize()를 실행해야 하는 객체
    • F-Queue라는 대기열에 추가됨
      • 죽음에 직면한 객체가 부활할 수 있는 마지막 기회
      • 메서드 수행 이후, 참조 체인상의 아무 객체와 다시 연결되면 부활됨
      • 오직 한번만 허용됨
    • 또 다른 스레드에 의해 finalize() 메서드가 수행됨

 

3. 메서드 영역 회수하기

지원 시기
  • JDK 12부터 지원
  • 효율이 좋지 않았음

 

대상 
  • 상수 (런타임 상수 풀)
  • 클래스
    • 이 클래스의 인스턴스가 모두 회수된 경우
    • 이 클래스의 클래스 로더가 모두 회수된 경우
    • 이 클래스 관련 Class 객체나 Reflection 메서드가 존재하지 않을 경우

 

매개변수
  • -Xnoclassgc: 클래스 회수 여부 설정
  • -verbose:class: 클래스 로드 정보 출력
  • -Xlog:class+load=info: 클래스 로드 정보 출력
  • -Xlog:class+unload=info: 클래스 언로드 정보 출력

 

사용
  • 바이트코드 프레임워크를 많이 사용하는 경우 (리플렉션, 동적 프록시, CGLib)
  • OSGi (JSP, User Classloader)