JVM 메트릭 이해를 위한 G1 GC 개념

윤희종·2026년 5월 22일

기술 블로그

목록 보기
3/11

그라파나를 통해 서버 성능 메트릭 지표를 분석하는데 있어서 GC에 대한 이해를 빼놓고 해석하는데 어려움이 있었습니다. 이번 포스팅에선, 메모리 지표를 제대로 이해하기 위해 GC에 어떤 종류가 있고 언제 발생하는지 알아보도록 하겠습니다.

G1GC

G1 GC Grabage First Garbage Collector의 약자로써, Garbage가 많은 것부터 회수하는 Garbage Collector 라고 합니다. G1GC가 이전까지의 GC와 가장 큰 차이점은 목표 정지 시간(pause time goal / target pause time)이라는 개념이 존재하는 것입니다. G1GC는 GC의 가장 큰 문제점인 STW시간을 최소화 하기위한 목표로 만들어진 GC이며, STW시간을 최대한 목표 정지 시간에 맞추는것을 목표로 합니다.

G1GC - 최소 단위 Region

G1GC는 힙 공간을 Region이라는 최소한의 단위로 관리하며, 각 Region은 4가지 상태 Free, Eden, Survivor, Old로 나뉩니다.

  • Free
    어떤 객체도 할당되지 않은 Region 입니다. G1GC는 이를 새로운 객체에 할당하게 됩니다.
  • Eden
    객체가 처음 생성될때 할당되는 영역입니다.
  • Survivor
    에덴 영역에서 GC를 통과한 객체가 할당되는 영역입니다.
  • Old
    서바이버 영역에서 여러번의 GC를 통과한 객체가 할당되는 영역입니다.

G1GC - GC의 종류

G1GC는 크게 세가지 GC(Young, Mixed, Full)가 존재합니다. 각 GC가 무엇인지 알아보며, 또한 Mixed 의 트리거 조건인 Concurrent Marking Cycle에 대해서도 알아보도록 하겠습니다.

1. Young GC

Young GC는 Eden, Survivor 만을 대상으로 GC를 수행하는 단계입니다. G1GC에서 가장 빈번하게 발생하며, 상대적으로 적은 Region을 대상으로 하기에 STW을 최소화한다는 특징이 있습니다.

  • 발생 조건
    현재 사이클에 배정된 eden region이 다 차는 순간 Young GC가 발생하게 됩니다.
    ( 사이클은 Young GC 간 사이를 의미합니다. )

  • 동작 순서

  1. 모든 Eden Region + 이번 차례의 Survivor Region을 스캔합니다.
  2. Evocation - Region에서 Live 객체를 새로운 Region으로 차곡차곡 이동.
  3. Promotion - 이동하는 객체의 나이에 따라, 도착지 Region이 정해집니다.
  4. 회수 - 정리된 Region을 Free 로 전환한다.

(pre 2.) Concurrent Marking Cycle

Concurrent Marking Cycle은 Old Region GC를 최적화 하기 위한 사전동작입니다. 객체 마킹 결과를 Region별로 집계해 "live가 적은 = 회수 가성비 좋은" 후보를 골라낸다. 이 집계를 통해 Garbage First를 만들어냅니다.

  • 발생 조건
    Old Generation Region이 전체 힙 영역의 45% 이상을 차지할때 발생하게 됩니다.
    ( JDK 9부터는 adaptive IHOP이 기본이라 이 45%가 고정값이 아니라 G1이 마킹 소요 시간과 할당 속도를 보고 동적으로 조정한다는 점 )

  • 동작 순서

  1. Initial Mark - GC root 에서 참조되는 객체들을 마킹합니다
  2. Root Region Scanning - (1) 객체(Survivor Region)가 참조하는 Old Region의 객체를 찾아 마킹합니다.
  3. Concurrent Marking - 전체 힙을 돌며 도달가능한 객체를 찾아 마킹합니다.
  4. Remark - 마킹 도중 애플리케이션에 의해 변경된 부분 다시 마킹합니다.
  5. Clenaup - 완전히 비어있는 Region을 Free Region으로 변경하며, Mixed GC 후보 Region을 선별한다.

> 마킹을 왜 하는가 ?
GC의 목적은 죽은 객체를 회수하는 것입니다. 그러려면 먼저 "어떤 객체가 죽었는가"를 알아야 하는데, 죽은 객체를 직접 찾는 건 불가능합니다. 죽은 객체는 아무도 참조하지 않아서 존재 자체를 알 방법이 없거든요. 그래서 발상을 뒤집습니다. 죽은 걸 찾는 대신, 살아있는 걸 전부 찾는다. 그러고 나면 "찾지 못한 나머지 = 죽은 것"이 됩니다. 이 "살아있는 객체를 전부 찾아서 표시하는 작업"이 바로 마킹(marking)입니다.

2. Mixed GC

Mixed GC는 Concurrent Marking Cycle의 종료 후 다음 Young GC 실행 시점에 Young GC대신 실행됩니다. Mixed GC는 기존 Young GC의 Region에 Concurrent Marking Cycle의 결과인 Mixed GC Candidate Regions까지 더해 GC를 실행합니다.

목표 정지 시간을 만족하기 위해 Old Region을 나눠서 GC를 수행합니다.

  • 발생 조건
    Young GC의 실행주기 사이에서 Concurrent Marking Cycle이 종료됐을 때 실행됨

3. Full GC

Full GC는 모든 힙을 대상으로 실행되는 최종 GC입니다. 모든 힙을 대상으로 하기에 STW기간이 상당히 길며, 이에 따라 어플리케이션 스레드에 큰 영향을 미치는 GC입니다.

Young/Mixed GC의 단위가 Region이라면, Full GC의 단위는 Object입니다. Full GC는 Region 내부의 단편화를 제거하기 위해 모든 객체를 최소한의 Region에 할당되도록 정리하며, 이를 Compaction이라 합니다.

  • 발생 조건
  1. Homongous Object를 위한 Old Region 부족시 발생합니다.
  2. Young, Mixed GC에서 Promotion, Evacuation을 위한 Region이 부족할때 발생합니다.

정리

JVM의 GC, 그중에서도 G1 GC의 동작을 Region 단위 관리부터 Young·Mixed·Full GC까지 전반적으로 정리했습니다. Garbage First라는 이름이 왜 붙었는지(회수 가성비가 좋은 Region부터 수집한다는 점) 이해할 수 있었으며, 특히, 목표 정지 시간을 만족하기 위해 Muxed GC Candidate Region 을 나눠서 실행한단 점이 인상깊었습니다. 서버의 성능 메트릭 지표를 더 깊게 이해할 수 있었으며, 앞으로의 성능 개선에 더 의미있는 결과를 만들 수 있을 것 같습니다.

감사합니다.

profile
이건 나는 게 아냐, 멋지게 추락하는거지

0개의 댓글