[Java] Garbage Collection

2025. 1. 2. 12:56·Java
728x90
반응형

Garbage Collection 개념

  • 가비지 컬렉션(Garbage Collection, GC): 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거하는 프로세스
  • 가비지 컬렉터가 없어 수동으로 메모리 할당과 해제를 해주어야 하는 C/C++과 달리, Java는 가비지 컬렉터가 메모리 관리를 대신 수행해줌
    • => 메모리 누수(Memory Leak) 문제에서 대해 관리없이 개발에만 집중 가능
  • 가비지 컬렉션(GC)이 한번쓰이고 버려지는 객체들을 주기적으로 비워줌 => 한정된 메모리를 효율적으로 사용 가능
  • 단점
    • 메모리가 언제 해제되는지 정확하게 알 수 없어 제어하기 힘듦
    • Stop-The-World(STW): 가비지 컬렉션(GC)이 동작하는 동안에는 JVM이 동작을 멈추는 현상 => 오버헤드 발생
      • GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread가 멈추게 됨
      • STW 시간을 최소화하는 것이 중요 = GC 튜닝

과거 인터넷 익스프롤러는 GC가 너무 빈번하게 실행되어 성능 이슈가 있었음

GC 대상

GC 대상 여부는 도달성(Reachability)라는 개념을 적용함

  • Reachable: 객체가 참조되고 있는 상태로, 객체에 레퍼런스가 있음
  • Unreachable: 객체가 참조되고 있지 않은 상태로, 객체에 유효한 레퍼런스가 없음 = GC 대상
  • JVM 메모리에서는 객체들은 실질적으로 Heap영역에서 생성되고 Method Area이나 Stack Area 에서는 Heap Area에 생성된 객체의 주소만 참조하는 형식으로 구성됨.
  • 하지만, Heap Area 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제될 수 있음 (by 메서드 종료 등의 특정 이벤트)
    • => Heap영역에서 어디서든 참조하고 있지 않은 객체(Unreachable)들이 발생
    • => 이러한 객체들을 주기적으로 가비지 컬렉터가 제거하는 것

GC 청소 방식 - Mark And Sweep

  • 표시-정리 알고리즘(Mark-Sweep): 다양한 GC에서 사용되는 객체를 솎아내는 내부 알고리즘 (가비지 컬렉션이 동작하는 아주 기초적인 청소 과정)
    • Mark 과정: 참조되는 모든 객체를 표시하는 과정으로, Root Space로부터 그래프 순회를 통해 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾아서 마킹
      • Root Space: Heap 메모리 영역을 참조하는 method area, static 변수, stack, native method stack
        • 즉, Method Area의 static 변수, Stack의 로컬 변수, Native Method Stack의 JNI 참조 등
    • Sweep 과정 : 참조하고 있지 않은 객체(마킹되지 않은 객쳬) 즉 Unreachable 객체들을 Heap에서 제거
      • 메모리 단편화 문제: Sweep 과정으로 삭제된 객체의 메모리 공간이 불연속적일 수 있음..
        • => 크기가 큰 객체를 할당할 때 메모리 할당에 어려움이 있을수 있음 => Compact 과정을 거쳐 해결
    • Compact 과정 : Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축
      • 가비지 컬렉터 종류에 따라 하지 않는 경우도 있음
  • Mark-Sweep 방식을 통해 루트로부터 연결이 끊긴 순환 참조되는 객체들을 모두 지울 수 있음

GC 동작 과정

세대별 가비지 컬렉션(Generation Garbage Collection)

  • JVM의 힙(heap) 영역은 동적으로 레퍼런스 데이터가 저장되는 공간으로, GC 대상이 되는 공간
    • 객체는 대부분 일회성되며, 메모리에 오랫동안 남아있는 경우는 드물다는 것을 전제로 설계되었음 (Weak Generational Hypothesis)
    • 이러한 특성을 이용해 JVM 개발자들은 보다 효율적인 메모리 관리를 위해, 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누게 되었음
  • 세대별 가비지 컬렉션(Generation Garbage Collection)
    • Young 영역(Young Generation)
      • 새롭게 생성된 객체가 할당(Allocation)되는 영역
      • 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라짐
      • Minor GC: Young 영역에 대한 가비지 컬렉션(Garbage Collection)
    • Old 영역(Old Generation)
      • Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
      • Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생
      • Major GC(또는 Full GC): Old 영역에 대한 가비지 컬렉션(Garbage Collection)
  • Old 영역이 Young 영역보다 크게 할당되는 이유
    • Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않고, 큰 객체들은 Young 영역이 아니라 바로 Old 영역에 할당되기 때문
  • Young 영역은 더 효율적인 GC를 위해 다시 3가지 영역(Eden, Survival 0, Survival 1)으로 나뉨
    • Eden
      • new를 통해 새로 생성된 객체가 위치
      • 정기적인 garbage 수집 후 살아남은 객체들은 Survivor 영역으로 보냄
    • Survival 0 / Survival 1
      • 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역
      • Survivor 영역의 제한 조건으로 Survivor 영역 중 반드시 1개는 사용되어야 하고, 나머지는 비어 있어야 함
      • 두 Survivor 영역에 모두 데이터가 존재하거나, 모두 사용량이 0이라면 현재 시스템이 정상적인 상황이 아니라는 것

Minor GC

  • 모든 객체는 처음에는 Young Generation에 생성
  • Young Generation의 공간은 Old Generation에 비해 상대적으로 작기 때문에 메모리 상의 객체를 찾아 제거하는데 적은 시간이 걸림
  • 과정
    1. Eden 영역에 처음 생성된 객체 위치
    2. Eden 영역이 꽉차게 되고 Minor GC가 실행
    3. Mark 동작을 통해 reachable 객체를 탐색
    4. Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동
    5. Eden 영역에서 사용되지 않는 객체(unreachable)의 메모리를 해제(sweep)
    6. 살아남은 모든 객체들은 age값이 1씩 증가
      • age 값: Survivor 영역에서 객체의 객체가 살아남은 횟수를 의미하는 값
      • age 값이 임계값에 다다르면 Promotion(Old 영역으로 이동) 여부를 결정
      • 이 age의 기본 임계값은 31
    7. 다시 Eden 영역에 신규 객체들로 가득 차게 되면 다시한번 Minor GC 발생하고 mark
      • 이때, Survivor 0에 있는 객체들도 marking 대상임
    8. marking 한 객체들을 비어있는 Survival 1으로 이동하고 sweep
    9. 다시 살아남은 모든 객체들은 age가 1씩 증가
    10. 1 ~ 9 과정을 반복

Major GC(= Full GC)

  • Old Generation의 객체들은 거슬러 올라가면 처음에는 Young Generation에 의해 시작되었으나, GC 과정 중에 제거되지 않은 경우 age 임계값이 차게되어 이동된 녀석들
  • Major GC는 객체들이 계속 Promotion되어 Old 영역의 메모리가 부족해지면 발생
    • Old 영역의 데이터가 가득 차면 GC를 실행하는 단순한 방식
  • 과정
    1. Survivor 영역에 있는 객체의 age가 임계값(여기선 8로 설정)에 도달하게 되면, 이 객체들은 Old Generation 으로 이동 = Promotion 과정
    2. Promotion이 반복되어 Old Generation 영역의 공간(메모리)가 부족하게 되면 Major GC가 발생
      • Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제
  • Old Generation은 Young Generation에 비해 상대적으로 큰 공간을 가지고 있어, 이 공간에서 메모리 상의 객체 제거에 많은 시간이 걸림
    • Minor GC: 0.5 ~ 1초
    • Major GC: Minor GC의 10배 이상의 시간 => Stop-The-World 문제 발생
    • STW 문제를 최소화하기 위해 다양한 GC 알고리즘들이 등장

GC 알고리즘

여기서 소개할 GC 알고리즘은 모두 설정을 통해 Java에 적용할수 있다. 즉, 상황에 따라 필요한 GC 방식을 설정해서 사용할 수 있다!

Serial GC

  • 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 GC
  • 싱글 스레드이기에 가장 stop-the-world 시간이 길다
  • Minor GC 에는 Mark-Sweep을 사용, Major GC에는 Mark-Sweep-Compact를 사용
  • 실무에서 사용하는 경우는 없다(CPU 코어가 1개인 경우에만 사용)

Serial GC 실행 명령어

java -XX:+UseSerialGC -jar Application.java

Parallel GC

  • Java 8의 기본 GC 알고리즘
  • Serial GC와 기본적인 알고리즘은 같지만, Young 영역의 Minor GC를 멀티 쓰레드로 수행 (Old 영역은 여전히 싱글 쓰레드)
  • => Serial GC에 비해 stop-the-world 시간 감소

Parallel GC 실행 명령어

java -XX:+UseParallelGC -jar Application.java 
# -XX:ParallelGCThreads=N : 사용할 쓰레드의 갯수

Parallel Old GC(Parallel Compacting Collector)

  • Parallel GC를 개선한 버전
  • Young 영역 뿐만 아니라, Old 영역에서도 멀티 쓰레드로 GC 수행
  • 새로운 가비지 컬렉션 청소 방식인 Mark-Summary-Compact 방식을 이용

Parallel Old GC 실행 명령어

java -XX:+UseParallelOldGC -jar Application.java
# -XX:ParallelGCThreads=N : 사용할 쓰레드의 갯수

CMS GC(Concurrent Mark Sweep)

  • 애플리케이션의 쓰레드와 GC 쓰레드가 동시에 실행되어 stop-the-world 시간을 최대한 줄이기 위해 고안된 GC
  • 원리: Reachable 한 객체를 한번에 찾지 않고 나눠서 찾는 방식 사용 (4 STEP)
    • Initial Mark
    • Concurrent Mark
    • Remark
    • Concurrent Sweep
  • 장점: Stop-the-World 시간 감소
  • 단점
    • GC 대상 파악 과정이 매우 복잡함
    • Compact 과정이 없어서 메모리 파편화가 발생할 수 있고, 처리량이 증가할 때 예측할 수 없는 STW가 발생 가능
  • Java 14에서 사용이 중지

CMS GC 실행 명령어

# deprecated in java9 and finally dropped in java14
java -XX:+UseConcMarkSweepGC -jar Application.java

G1 GC(Garbage First)

  • CMS GC를 대체하기 위해 jdk 7 버전에서 최초로 release된 GC
  • 원리
    • 힙을 Young / Old 영역이 아닌 완전히 다르고 더 작은 영역 개념인 Regoin으로 나눔
    • 전체 Heap 영역을 Region이라는 영역으로 체스판같이 분할 후, 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여
    • Eden, Survivor, Old 역할에 더해 Humongous와 Available/Unused라는 2가지 역할을 추가
      • Humongous: Region 크기의 50%를 초과하는 객체를 저장하는 Region
      • Available/Unused: 사용되지 않는 Region
    • 전체 Heap에 대해 탐색하지 않고 부분적으로 Region 단위로 탐색하여, garbage가 많은 Region에만 우선적으로 GC 수행
    • GC가 돌때마다 살아남으면 Eden → Survivor0 → Survivor1으로 순차적으로 이동하는 것이 아니라, 더욱 효율적이라고 생각하는 위치로 객체를 Reallocate(재할당)
    • 이러한 작업은 concurrent하게 수행되어 애플리케이션의 지연도 최소화 가능
  • 장점
    • Stop-the-World 시간을 예측 가능하게 줄이고, 힙을 더 세분화하여 효율적으로 가비지 컬렉션을 수행
    • 어떠한 GC 방식보다 처리 속도가 빠름
  • 단점: 몇몇 특정 상황에서 처리량이 감소
  • Java 9+ 버전의 디폴트 GC
  • 4GB 이상의 힙 메모리, Stop the World 시간이 0.5초 정도 필요한 상황에 사용 (Heap이 너무작을경우 미사용 권장)

G1 GC 실행 명령어

java -XX:+UseG1GC -jar Application.java

Shenandoah GC

  • 강력한 Concurrency와 가벼운 GC 로직 -> heap 사이즈에 영향을 받지 않고 일정한 pause 시간이 소요가 특징
  • 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결
  • 장점: 일시 중지 시간을 매우 짧게 유지하면서도 전반적인 처리량을 유지 가능
  • 단점: 일부 애플리케이션에 대한 최적화가 필요할 수 있으며, 모든 플랫폼에서 지원되지 않을 수 있음
  • Java 12에 릴리즈

Shenandoah GC 실행 명령어

java -XX:+UseShenandoahGC -jar Application.java

ZGC(Z Garbage Collector)

  • 대량의 메모리(8MB ~ 16TB)를 low-latency로 잘 처리하기 위해 디자인 된 GC
  • 원리: G1의 Region 처럼, ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는 2mb 배수로 동적으로 운영
  • 장점: 힙 크기가 증가하더라도 'stop-the-world'의 시간이 10ms를 넘지 않음
  • 단점: 일부 응용 프로그램에서는 ZGC가 다른 가비지 컬렉터보다 성능이 떨어질 수도 있고 메모리 사용량이 더 클 수 있음
  • 일반적으로는 성능 및 일시 중지 시간 측면에서 우수한 결과를 보이는 편
  • Java 15에 릴리즈

ZGC 실행 명령어

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar Application.java
728x90
반응형

'Java' 카테고리의 다른 글

[Java] 예외 처리  (2) 2025.01.03
[Java] 자바 기본 개념 정리 (기본 문법 제외)  (2) 2025.01.02
[Java] JVM / JRE / JDK  (3) 2025.01.01
[Java] Annotation  (0) 2024.10.10
[Java] Reflection  (0) 2024.10.10
'Java' 카테고리의 다른 글
  • [Java] 예외 처리
  • [Java] 자바 기본 개념 정리 (기본 문법 제외)
  • [Java] JVM / JRE / JDK
  • [Java] Annotation
mxruhxn
mxruhxn
소소하게 개발 공부 기록하기
    반응형
    250x250
  • mxruhxn
    maruhxn
    mxruhxn
  • 전체
    오늘
    어제
    • 분류 전체보기 (152)
      • Java (21)
      • Spring (6)
      • Database (13)
      • Operating Syste.. (1)
      • Computer Archit.. (0)
      • Network (24)
      • Data Structure (6)
      • Algorithm (11)
      • Data Infra (7)
      • DevOps (12)
      • ETC (27)
      • Project (21)
      • Book (1)
      • Look Back (1)
  • 블로그 메뉴

    • 링크

      • Github
    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.0
    mxruhxn
    [Java] Garbage Collection
    상단으로

    티스토리툴바