본문 바로가기

IT/JAVA

Java Garbage Collection

반응형

Java Garbage Collection

NAVER D2

1. 가비지 컬렉션 과정 - Generational Garbage Collection

1.1. 'stop-the-world'

  • GC를 실행하기 위해 JV 이 어플리케이션 실행을 멈추는 것
  • GC를 수행하는 쓰레드를 제외한 모든 쓰레드는 작업을 멈춤
  • GC튜닝이란 stop-the-world 를 줄이는 것이다.

1.2. 명시적 해제

  • 명시적으로 해제하려고 null을 할당하거나 System.gc()를 호출하는 경우도 있음 → System.gc()는 성능에 매우 큰 영향을 끼친다.(아마도 gc를 하면 stw 가 발생하여서 그런 것 같다.)

1.3. 두 가지 가설에 기반한 가비지 컬렉션

  • 대부분의 객체는 금방 접근 불가능 상태가 된다.
  • 왜??? 왜 이런 가설이?
  • 오래된 객체에는 젊은 객체로의 참조는 아주 적게 존재한다.

1.4. Young 영역과 Old 영역

  • 두가지 물리적 공간으로 나뉨
  • Young / Old
  • Young 영역
    • 새롭게 생성한 객체의 대부분이 여기에 위치
    • 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다가 사라짐
    • 왜 금방 접근 불가능 상태?
    • 객체가 사라질 때 Minor GC가 발생함
  • Old 영역
    • 접근 불가능 ㅅ아태가 되지 않아 Young 영역에서 사라 남은 객체가 복사됨
    • Young 보다 크게 할당하며, 크기가 큰 만큼 Young 보다 GC는 적게 발생함
    • 왜 크게 할당?
    • Old 영역에서 GC가 발생하면 Major GC(Full GC)가 발생함
  • Permanent Generation 영역
    • Method Area라고도 한다.
    • 이곳에서 GC가 발생하면 Major GC 가 발생
    • JAVA8 이상에서는 사라짐
  • Old 영역에 있는 객체가 Young 영역의 객체를 참조하는 경우
    • Old 영역에는 512바이트짜리 카드 테이블이 존재
    • Old 영역 객체가 Young 영역 객체를 참조할 때마다 정보를 표시
    • Young 영역 GC 실행 시 Old 영역을 뒤지는 것이 아니라 카드 테이블을 참조하여 GC 대상 선별

1.5. Young 영역의 구성

  • Eden 영역 / Survivor 영역 (2개) , 총 3개 영역으로 나뉨
  • 새로 생성한 객체는 Eden 영역에 위치
  • GC가 발생한 후 살아남은 객체는 Survivor 영역 중 하나로 이동된다.
  • 하나의 Survivor 영역이 가득 차게 되면 그중에서 살아남은 객체를 다른 Survivor 영역으로 이동한다.
  • 그리고 가득 찼던 Survivor 영역은 아무 데이터도 없는 상태로 된다.
  • 실제로는 Survivor 포인터를 가지고 단순 변경이기 때문에 Minor GC 때에 리소스가 많이 들지 않는다.
  • 이 과정을 반복하다 살아남은 객체를 Old 영역으로 이동시킨다.
  • Survivor 영역 중 하나는 반드시 비어 있어야 한다.

1.6. Old 영역에 대한 GC

  • Serial GC
  • Parallel GC
  • Parallel Old GC(Parallel Compacting GC)
  • Concurrent Mark & Sweep GC(이하 CMS)
  • G1(Garbage First) GC

2. GC의 종류

2.1. Serial GC

  • JDK 5, 6에서 기본으로 사용되는 GC이다. 싱글 스레드로 Minor GC와 Major GC를 수행하기 때문에 Stop-The-World 시간이 다른 GC에 비해 상대적으로 긴 편이다.
  • Serial GC를 서버 환경에서 사용하는 것은 바람직하지 않다. 하지만 빠른 응답속도가 필요하지 않거나 클라이언트 스타일의 장비에선 사용할 수도 있다.

2.2. Parallel GC

  • Minor GC를 수행할 때 멀티 스레드를 사용하는 GC이다.
  • 기본적으로 JVM이 구동되는 환경의 CPU 코어 개수에 맞춰서 N개의 GC가 수행된다
  • Parallel GC를 활성화해도 장비의 CPU가 단일 코어면 Serial GC로 동작한다.

2.3. Parallel Old GC

  • Parallel Old GC는 JDK 5 update 6부터 제공한 GC 방식
  • Parallel GC와 비교하여 Old 영역의 GC 알고리즘만 다르다.
  • Mark-Summary-Compaction 단계
    • 마킹 → Summary → Compaction
  • Mark-Sweep-Compaction 알고리즘의 Sweep 단계와 다르며, 약간 더 복잡한 단계를 거친다.

2.4. Concurrent Mark Sweep(CMS) GC

  • CMS GC는 Old 영역을 대상으로 이루어진다
  • Initial Mark 단계 → Concurrent Mark 단계 → Remark 단계→ Concurrent Sweep 단계
    • Initial Mark 단계 : GC Root에서 참조 Tree에서 제일 상단에 있는 객체만 선별하는 과정. 탐색 깊이가 얕아서 STW 시간이 매우 짧다
    • Concurrent Mark 단계 : Initial Mark 단계에서 살아남은 객체의 참조를 따라가며 살아있는 객체를 찾는다, 이 단계의 특징은 다른 스레드가 실행 중인 상태에서 동시에 진행된다는 것
    • Remark 단계 : Remark에서는 Concurrent Mark를 수행하는 동안 객체의 참조가 끊기거나, 새롭게 생긴 객체가 없는지 다시 한번 확인한다.
    • Concurrent Sweep 단계 : 쓰레기를 정리하는 작업을 실행한다. 이 작업도 다른 스레드가 실행되고 있는 상황에서 진행한다.
  • 멀티 쓰레드와 작업 단위 특징상 STW 가 아주 짧다.
  • 단점으로는
    • 다른 GC 방식보다 메모리와 CPU를 더 많이 사용한다.
    • Compaction 단계(조각 모음이라고 보면 됨)가 기본적으로 제공되지 않는다.

2.5. G1 GC

  • CMS GC와 다른 점은 G1 GC는 메모리를 페이징 하듯이 논리적인 단위(Region)로 나눠서 관리한다
  • Region이라는 논리적인 단위로 메모리를 관리하여 CMS와 달리 Compaction 단계를 진행하고 메모리 단편화 문제 제거
  • STW의 시간을 예측할 수 있다는 것이 G1 GC의 큰 장점
  • G1 GC는 Initial Mark 단계를 멀티 스레드로 수행한다.
  • 이 단계 후에 G1 GC는 Region 중 어떤 Region이 GC후에 메모리를 많이 반환할지 알게 된다.
  • G1 GC는 비 참조 객체를 수집하며 살아있는 객체는 하나의 Region에 이동하는 작업을 진행하는데, 이 과정에서 Compaction이 이루어진다.

2.5.1. G1의 Young GC

  • Young GC가 발생하면 Young GC에서 살아남은 객체들이 한 개 이상의 Survivor Region에 차곡차곡 이동(이 과정에서 STW가 발생)
  • Young GC가 끝난 후에는 살아남은 객체가 Survivor 혹은 Old Region으로 이동되어 Compaction 된 상태가 된다.

2.5.2 G1의 Old GC

  • 앞에서 소개한 다른 GC와 다르게 G1 GC는 살아있는 객체(live object)를 찾아서 비어있는 Region에 이동 후 남은 객체들을 삭제하는 방식을 사용
    • Initial Mark : STW가 발생한다. 보통 Young GC의 Mark 단계에서 같이 이루어지는데, Survivor Region 중 Old 영역의 객체를 참조하고 있는 객체가 존재하는 Region을 식별한다.
    • Root Region Scanning : Initial Mark 단계에서 식별한 Region에서 Old 영역의 객체를 참조하고 있는 Young 영역의 객체를 식별한다.
    • Concurrent Marking : Heap 전체에 걸쳐 참조되고 있는 객체(live object)를 찾는다.
    • Remark : STW가 발생한다. Concurrent Mark 단계의 결과를 검증한다.
    • Cleanup & Copying : 참조되고 있는 객체(live object)를 비어있는 영역으로 옮기고, 참조되지 않는 객체들을 삭제 후에 비게 된 영역을 Unused 상태로 만든다, 이때, 참조되고 있는 객체들을 비어있는 영역으로 옮기는 과정에서 STW가 발생한다.
반응형