본문 바로가기
개발&프로그래밍

[JAVA] 가비지 컬렉션 동작 원리와 모니터링 방법

by 재아군 2024. 11. 14.

[JAVA] 가비지 컬렉션 동작 원리와 모니터링 방법

 

Java 애플리케이션의 성능을 최적화하기 위해서는 가비지 컬렉션(GC)의 동작 원리를 이해하고 적절히 모니터링하는 것이 중요하다.

이 글에서는 GC의 기본 개념부터 실전 모니터링 방법까지 자세히 알아본다.

 

 

 

JVM 메모리 구조

JVM 메모리는 크게 다음과 같이 구분된다:

 

Heap 영역

[Young Generation]
- Eden Space
- Survivor Space 0
- Survivor Space 1

[Old Generation]
- Tenured Space

 

Non-Heap 영역

- Metaspace (Java 8+)
- Code Cache
- Thread Stacks

 

각 영역의 특징

  1. Young Generation
    • 새로 생성된 객체가 할당되는 영역
    • Minor GC가 발생하는 영역
    • 대부분의 객체가 빠르게 사라짐
  2. Old Generation
    • 오래 살아남은 객체가 이동하는 영역
    • Major GC가 발생하는 영역
    • GC 시간이 더 오래 걸림
  3. Metaspace
    • 클래스 메타데이터 저장
    • Java 8부터 PermGen을 대체
    • 네이티브 메모리 사용

 

GC 알고리즘 비교

 

Serial GC

-XX:+UseSerialGC
  • 단일 스레드로 GC 수행
  • 간단하지만 성능이 제한적
  • 적은 메모리와 CPU 코어에 적합

 

Parallel GC

-XX:+UseParallelGC
  • 다중 스레드로 GC 수행
  • 처리량(Throughput) 중시
  • 대규모 배치 작업에 적합

 

CMS GC (Concurrent Mark Sweep)

-XX:+UseConcMarkSweepGC  # Java 9부터 deprecated
  • 애플리케이션 스레드와 동시 실행
  • 짧은 일시 정지 시간
  • 메모리와 CPU 사용량이 높음

 

G1 GC (Garbage First)

-XX:+UseG1GC  # Java 9부터의 기본 GC
  • 영역을 작은 단위로 나눠서 관리
  • 예측 가능한 일시 정지 시간
  • 대용량 힙 메모리에 적합

 

ZGC (Java 11+)

-XX:+UseZGC
  • 초저지연 GC
  • 테라바이트 급 힙 처리 가능
  • 일시 정지 시간 10ms 미만

 

GC 튜닝 팁

 

1. 힙 크기 설정

-Xms4g  # 초기 힙 크기
-Xmx4g  # 최대 힙 크기

 

2. Young Generation 크기 조정

-XX:NewRatio=2  # Old:Young = 2:1
-XX:NewSize=2g  # Young 영역 초기 크기
-XX:MaxNewSize=2g  # Young 영역 최대 크기

 

3. GC 로깅 활성화

-Xlog:gc*:file=gc.log:time,uptimemillis:filecount=5,filesize=100m

 

4. 모니터링 지표 설정

// JMX를 통한 모니터링 설정
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.authenticate=false

 

GC 로그 분석 방법

 

1. 기본 GC 로그 형식

[2023-11-14T10:15:30.123+0900] GC(100) Pause Young (Normal) (G1 Evacuation Pause)

 

2. 주요 분석 포인트

  • GC 발생 빈도
  • GC 소요 시간
  • 메모리 회수량
  • Full GC 발생 여부

 

3. 로그 분석 도구

# GCViewer 실행
java -jar gcviewer.jar gc.log

# jstat 사용
jstat -gc <pid> 1000

 

실전 모니터링 예제

 

1. JVM 상태 모니터링

public class GCMonitoring {
    public static void getGCStats() {
        List<GarbageCollectorMXBean> gcBeans = 
            ManagementFactory.getGarbageCollectorMXBeans();

        for (GarbageCollectorMXBean gcBean : gcBeans) {
            System.out.println("GC Name: " + gcBean.getName());
            System.out.println("Collection count: " + 
                gcBean.getCollectionCount());
            System.out.println("Collection time: " + 
                gcBean.getCollectionTime() + "ms");
        }
    }
}

 

2. 메모리 사용량 모니터링

public class MemoryMonitoring {
    public static void getMemoryStats() {
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();

        System.out.println("Init Heap: " + 
            heapUsage.getInit() / 1024 / 1024 + "MB");
        System.out.println("Used Heap: " + 
            heapUsage.getUsed() / 1024 / 1024 + "MB");
        System.out.println("Max Heap: " + 
            heapUsage.getMax() / 1024 / 1024 + "MB");
    }
}

 

문제 해결 시나리오

1. 높은 GC 부하

증상: GC가 너무 자주 발생
해결: Young Generation 크기 증가
-XX:NewRatio=3

 

2. Full GC 빈발

증상: Full GC가 자주 발생
해결: Old Generation 크기 조정
-XX:CMSInitiatingOccupancyFraction=75

 

3. 긴 GC 일시정지

증상: GC 일시정지 시간이 김
해결: G1 GC로 전환 및 목표 일시정지 시간 설정
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

 

모니터링 체크리스트

  1. 일간 체크항목
    • GC 발생 빈도
    • 메모리 사용량 추이
    • Full GC 발생 여부
  2. 주간 체크항목
    • GC 시간 추이 분석
    • 메모리 누수 징후 확인
    • 힙 덤프 분석
  3. 월간 체크항목
    • GC 설정 최적화 검토
    • 성능 지표 리포트 작성
    • 시스템 확장 계획 수립

 

댓글