본문으로 건너뛰기

G1(Garbage-First) GC 동작 과정

Java 17·21의 기본 GC인 G1GC(Garbage-First Garbage Collector)
힙을 잘게 나누고, 쓰레기가 많은 곳부터 조금씩 치운다”는 개념으로 설계된 GC입니다.


G1GC 한 줄 요약

G1GC는 힙을 Region 단위로 나누고,
Garbage(쓰레기)가 많은 Region부터 우선적으로 수집해
멈춤 시간을 예측 가능하게 만드는 GC입니다.


1. G1GC는 힙을 이렇게 나눈다

기존 GC는 힙을 크게 Young / Old 영역으로 나눠 관리했지만,
G1GC는 힙을 같은 크기의 작은 조각(Region) 으로 나눕니다.

Heap = [Region][Region][Region][Region]...

  • Region 크기: 보통 1~32MB
  • 각 Region은 상황에 따라 역할이 바뀜
    • Eden
    • Survivor
    • Old

👉 Region은 고정 역할이 아니라 동적으로 역할이 바뀐다는 점이 핵심입니다.


2. 객체는 어디에 생성될까? (Eden Region)

새로 생성되는 객체는 대부분 Eden Region에 할당됩니다.

Eden이 가득 차면?

  • Young GC 발생
  • 아주 짧은 Stop-The-World(STW) 발생
  • 살아있는 객체만 골라:
    • Survivor 또는 Old Region으로 이동
  • Eden Region은 통째로 비워서 재사용

👉 복사(Evacuation) 방식이라 빠르고 단편화가 적음


3. 객체가 오래 살아남으면? (Old Region)

Young GC를 여러 번 버틴 객체는 Old Region으로 이동합니다.

문제는 Old가 커질수록,

“어디부터 치워야 효율적일까?”
를 판단해야 한다는 점입니다.


4. Concurrent Marking (조사 단계)

Old 영역이 일정 수준 이상 차면,
G1GCConcurrent Marking 단계를 시작합니다.

이 단계에서 하는 일

애플리케이션이 실행되는 동안
Old Region을 하나씩 살펴보며 다음을 계산합니다.

  • 살아있는 객체 비율
  • 쓰레기(Garbage) 비율

중요한 점:

  • 대부분 애플리케이션과 동시에 실행
  • 중간에 아주 짧은 STW만 발생

👉 이 단계는 “치우는 단계”가 아니라 “어디를 치울지 정하는 단계” 입니다.


5. Mixed GCG1GC의 핵심

Concurrent Marking이 끝나면,
드디어 G1GC 이름의 의미가 드러납니다.

Mixed GC란?

Young Region + Garbage가 많은 Old Region 일부를 함께 회수하는 GC

왜 “Garbage-First”인가?

Old Region 중에서도, 다음 기준에 해당하는 리전을 우선적으로(Garbage-First) 수집하기 때문입니다.

  • 쓰레기(Garbage)가 많고
  • 적은 비용으로 많은 메모리를 회수할 수 있는 곳

6. Pause Time을 어떻게 관리할까?

G1GC의 중요한 목표는

“GC로 인한 멈춤 시간을 예측 가능하게 만들자

이므로, 다음과 같은 옵션을 제공합니다.

-XX:MaxGCPauseMillis=200
  • “한 번의 GC는 200ms 이내로 끝내자”는 목표값
  • G1GC는 이 목표에 맞춰
  • 한 번에 수집할 Region 개수를 자동으로 조절

👉 한 번에 다 치우지 않고 조금씩 나눠서 치움


7. Full GC는 언제 발생할까? (가능하면 피한다)

G1GC도 다음 상황에서는 Full GC가 발생할 수 있습니다.

  • 객체를 옮길 빈 Region이 부족할 때
  • Old 영역 증가 속도를 GC가 따라가지 못할 때
  • 매우 큰 객체(Humongous Object)가 많을 때

👉 운영 환경에서 Full GC는 반드시 원인 분석 대상입니다.


8. G1GC 전체 흐름 요약

객체 생성 → Eden
Eden 가득 → Young GC
오래 생존 → Old
Old 커짐 → Concurrent Marking
쓰레기 많은 곳 → Mixed GC
(Full GC는 최대한 회피)


9. 실무에서 많이 넣는 GC 튜닝 옵션(설정값)

실무 공통

  • 힙 사이징
-Xms4g -Xmx4g

# -Xms: JVM 시작 시 힙 크기 (initial heap size)
# -Xmx: JVM이 사용할 수 있는 최대 힙 크기 (max heap size)

운영에서는 보통 Xms = Xmx로 고정(리사이징 비용/변동 최소화)
Xms와 Xmx를 같게 두면 JVM이 힙 크기를 늘렸다 줄였다(resize) 하느라 쓰는 비용과 성능 변동을 막을 수 있다.

  • GC 로그 (무조건)
-Xlog:gc*,safepoint:file=/var/log/gc.log:time,uptime,level,tags
  • OOM 진단
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/heapdump.hprof
-XX:ErrorFile=/var/log/hs_err_pid%p.log

G1GC에서 자주 만지는 튜닝 옵션

  • 목표 pause 시간(soft goal)
-XX:MaxGCPauseMillis=200

너무 낮추면 CPU/처리량 희생 가능

  • 마킹 시작 시점(IHOP)
-XX:InitiatingHeapOccupancyPercent=45

Old가 빨리 차서 Mixed/FullGC 위험이면 더 낮춰서 일찍 마킹 유도

  • 스레드 수(환경 따라)
-XX:ParallelGCThreads=8
-XX:ConcGCThreads=2

CPU 코어/컨테이너 제한 있을 때 조정 (과다하면 앱 CPU 잠식)

  • 큰 객체/Region 관련(가끔)
-XX:G1HeapRegionSize=8m

기본 자동이 대부분 정답이라 특수 케이스에서만 조정


G1GC는 힙을 잘게 나눠
쓰레기가 많은 영역부터 조금씩 치우며
멈춤 시간을 관리하는 GC입니다.

G1GC는 “한 번에 다 치우는 GC”가 아니라
“조금씩, 예측 가능하게 치우는 GC”입니다.

그래서:

  • 대용량 힙
  • 서버 애플리케이션
  • Java 17·21 환경

에서 기본 GC로 사용되고 있습니다.

Loading comments...