자바칩

[Java] 가비지 컬렉션 (GC) 본문

Study/Java

[Java] 가비지 컬렉션 (GC)

아기제이 2024. 5. 19. 20:37
728x90

가비지 컬렉션의 작동 원리

가비지 컬렉션(Garbage Collection, GC)은 프로그램이 더 이상 사용하지 않는 메모리를 자동으로 해제하는 과정이다. 자바에서는 JVM이 가비지 컬렉터를 사용하여 이 작업을 수행한다. 기본적인 작동 원리는 다음과 같다.

  1. 객체 생성: 프로그램이 새로운 객체를 생성하면 힙(heap) 메모리 영역에 할당된다.
  2. 사용 중인 객체 추적: JVM은 프로그램이 참조하는 모든 객체를 추적한다.
  3. 미사용 객체 식별: 더 이상 참조되지 않는 객체는 "가비지"로 간주된다.
  4. 가비지 수집: 가비지 컬렉터가 주기적으로 실행되어 미사용 객체를 메모리에서 제거하고, 메모리를 재사용할 수 있게 한다.

G1GC와 기존의 가비지 컬렉션 방식 비교

G1GC(Garbage-First Garbage Collector)는 Java 7에서 도입된 가비지 컬렉터로, Java 9 이후 기본 가비지 컬렉터로 사용된다. G1GC는 이전 방식인 CMS(Concurrent Mark-Sweep)와 Parallel GC와 비교하여 다음과 같은 차별점이 있다.

  1. 영역 분할
    • 기존 방식(CMS, Parallel GC): 힙 메모리를 크게 두 부분(Young Generation, Old Generation)으로 나누어서 관리한다.
    • G1GC: 힙 메모리를 고정된 크기의 작은 영역(Region)으로 나누어 관리한다. 각 영역은 Young 또는 Old로 구분되며, 필요에 따라 역할이 바뀔 수 있다.
  2. 가비지 수집 방식
    • CMS: 멀티쓰레드를 사용하여 Young Generation과 Old Generation을 병행(mark and sweep) 방식으로 수집한다. 하지만 Old Generation의 단편화 문제로 인해 Full GC가 자주 발생할 수 있다.
    • Parallel GC: Young Generation은 병렬로 수집하고, Old Generation은 stop-the-world 이벤트 동안 병렬로 수집한다.
    • G1GC: 멀티쓰레드를 사용하여 영역 단위로 병렬 수집한다. 정해진 목표 시간 내에 가장 많은 가비지를 수집하도록 최적화된다.

G1GC의 가비지 컬렉션 과정에서 발생할 수 있는 문제점과 해결 방안

  1. 문제점
    • 추가적인 CPU 오버헤드: 멀티쓰레드 방식으로 인해 CPU 사용량이 증가할 수 있다.
    • 힙 메모리 단편화: 작은 영역 단위로 관리하기 때문에 단편화가 발생할 수 있다.
  2. 해결 방안
    • CPU 자원 최적화: '-XX:ConcGCThreads' 옵션을 조정하여 가비지 컬렉션에 사용할 쓰레드 수를 조절한다.
    • 힙 크기 조정: '-Xms'와 '-Xmx' 옵션으로 힙 크기를 적절히 설정하여 단편화를 최소화한다.
    • 주기적인 Full GC: '-XX:+ExplicitGCInvokesConcurrent' 옵션을 사용하여 주기적으로 Full GC를 실행, 단편화를 줄인다.

다양한 가비지 컬렉션 방식의 선택 기준 및 장단점

  장점 단점
G1GC - 예측 가능한 짧은 멈춤 시간
- 대규모 힙 메모리 관리에 효율적
- 설정과 튜닝이 복잡
- CPU 오버헤드가 클 수 있음
CMS - 애플리케이션 멈춤 시간이 짧음
- 낮은 지연 시간
- 힙 단편화 문제
- Full GC 발생 시 긴 멈춤 시간
Parallel GC - 전체적인 처리량이 높음
- 단순한 설정
- 멈춤 시간이 길 수 있음 (특히 대규모 힙 메모리에서)

 

실시간 시스템에서 가비지 컬렉션의 지연 시간을 최소화하기 위한 전략

  1. 적절한 GC 선택: 지연 시간이 중요한 실시간 시스템에서는 G1GC 또는 ZGC(저지연 가비지 컬렉터)와 같은 저지연 GC를 사용하는 것이 좋다.
  2. GC 튜닝: '-XX:MaxGCPauseMillis' 옵션을 사용하여 목표 멈춤 시간을 설정한다.
  3. 메모리 할당 최적화: 객체 할당과 해제를 줄이는 방향으로 코드를 최적화한다. 예를 들어, 객체 재사용 풀(Object Pool)을 사용한다.
  4. 쓰레드 조정: -XX:ConcGCThreads'와 같은 옵션을 통해 GC에 사용할 쓰레드 수를 조정하여 애플리케이션의 성능을 최적화한다.

대규모 힙 메모리를 관리할 때 G1GC의 성능을 최적화하는 방법

  1. 적절한 힙 크기 설정: '-XMS'와 '-Xmx'를 사용하여 힙 크기를 적절히 설정한다. 너무 작으면 자주 GC가 발생하고, 너무 크면 GC 시간이 길어질 수 있다.
  2. 영역 크기 조정: '-XX:G1HeapRegionSize' 옵션을 사용하여 영역 크기를 조정한다. 일반적으로 1MB에서 32MB 사이로 설정할 수 있다.
  3. 목표 멈춤 시간 설정: '-XX:MaxGCPauseMillis'를 사용하여 애플리케이션 요구에 맞는 목표 멈춤 시간을 설정한다.
  4. GC 로깅 활성화: '-Xlog:gc*' 옵션을 사용하여 GC 로그를 활성화하고, 로그를 분석하여 문제를 파악하고 최적화한다.
  5. Full GC 방지: '-XX:G1MixedGCLiveThresholdPercent' 옵션을 조정하여 Mixed GC가 더 자주 실행되도록 하여 Full GC 발생을 줄인다.

 

아래 링크의 블로그를 보고 가비지 컬렉션, 동작방식, G1GC를 공부하는 데에 도움이 많이 되었다.

https://youn0111.tistory.com/67

 

Java Garbage Collection(GC)란 무엇이고 동작방식과 G1GC에 대해

C와 같은 프로그래밍 언어에서 메모리 할당 및 할당 해제는 수동 프로세스입니다. 반면에, Java에서 메모리 할당 해제 프로세스는 Garbage Collection에 의해 자동으로 처리가 됩니다. [기본 프로세스]

youn0111.tistory.com