오늘은 여기까지

Garbage Collection 개념 및 동작 원리 본문

CS/자바

Garbage Collection 개념 및 동작 원리

dev-99 2024. 11. 27. 08:30

C/C++에서는 개발자가 직접 사용하지 않는 객체의 메모리를 해제해주어야 한다. 하지만 JAVA에서는 JVM이 구성된 JRE가 제공되며, 그 구성 요소 중 하나인 Garbage Collection이 자동으로 사용하지 않는 객체를 파괴한다.

GC를 해도 더이상 사용 가능한 메모리 영역이 없는데 계속 메모리를 할당하려고 하면, OutOfMemoryError가 발생하여 WAS가 다운될 수도 있다. 따라서 규모 있는 JAVA 애플리케이션을 효율적으로 개발하기 위해서는 GC에 대해 잘 알아야 한다.

Garbage Collection

JVM의 메모리는 총 5가지 영역(class, stack, heap, native method, PC)으로 나뉘는데, GC는 힙 영역만 다룬다.

GC는 객체의 접근 가능성(Reachability)를 기준으로 동작한다. 객체가 GC Root에서 참조될 수 없으면 “사용되지 않는 객체”로 간주한다.

일반적으로 아래와 같은 경우에 GC의 대상이 된다.

  1. 객체가 NULL인 경우
  2. 블럭 실행 종료 후, 블럭 안에서 생성된 객체
  3. 부모 객체가 NULL인 경우, 포함하는 자식 객체

GC는 `Weak Generational Hypothesis`에 기반한다.

 

1. Weak Generational Hypothesis

JVM의 Heap 영역은 처음 설계될 때 다음과 같은 2가지 전제로 설계되었다.

  • 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
  • 오래된 객체에서 새로운 객체로의 참조는 매우 적게 존재한다.

이 가설에 기반하여 JAVA는 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누게 되었다. Young 영역과 Old 영역으로 메모리를 분할하고, 신규로 생성되는 객체는 Young 영역에, 오랫동안 살아남은 객체는 Old 영역에 보관한다.

 

2. Generational Garbage Collection

 

 

  1. Young 영역 (Young Generation)
    • 새롭게 생성된 객체가 할당되는 영역
    • 대부분의 객체가 금방 Unreachable 상태가 되므로, 많은 객체가 Young 영역에 생성되었다가 사라진다.
    • Young 영역에 대한 GC를 Minor GC라고 부른다.
  2. Old 영역 (Old Generation)
    • Young 영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
    • Young 영역보다 크게 할당되고, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.
    • Old 영역에 대한 GC를 Major GC라고 부른다.
  3. Permanent 영역: Java8부터 Metaspace로 교체되며 제거되었다.
    • JVM이 클래스들과 메소드들을 설명하기 위해 필요한 메타데이터를 저장

 

예외적으로 Old 영역에 있는 객체가 Young 영역의 객체를 참조하는 경우도 존재한다. 이러한 경우를 대비해 Old 영역에는 카드 테이블(Card Table)이 존재한다.

 

카드 테이블에는 Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때마다 그에 대한 정보가 표시된다. 따라서 Young 영역에서 Minor GC가 실행될 때 모든 Old 영역 객체를 검사하지 않고, 카드 테이블만 조회하여 GC의 대상인지 식별할 수 있다.

 


 

 

 

 

Generational Garbage Collection 과정을 보기 전에, GC의 메모리 해제 과정을 먼저 살펴본다.

3. GC의 메모리 해제 과정

  1. Marking
    gc3
    • 참조 가능한 객체를 탐색하고 식별하는 과정이다. 모든 객체를 스캔해야 하므로 많은 시간을 소모한다.
    • 참조되는 객체는 파란색, 참조되지 않는 객체는 주황색이다.
  2. Normal Deletion
    gc4
    • 참조되지 않는 객체를 제거하고 메모리를 반환한다. 메모리 Allocator는 새로운 객체 생성을 대비해 반환되어 빈 블록의 참조 위치를 저장해둔다.
  3. Compacting
    gc5
    • 성능 향상을 위해 참조되지 않는 객체를 제거한 후 남은 객체들을 묶는다.

 

 

4. Generational Garbage Collection 과정

  1. 객체 할당 - 새로운 객체가 들어오면 Eden Space에 할당한다.
    gc6
  2. Eden space가 가득차면, Minor GC이 트리거된다.
    gc7
  3. Copying Referenced Objects
    gc8
    • 마킹 이후 참조 객체들은 첫 번째 survivor space(S0)로 이동되고, 비 참조 객체는 Eden space가 clear 될 때 반환된다.
  4. Object Aging
    gc9
    • 다음 Minor GC 때, Eden space에서는 같은 일이 일어난다. Eden space의 비 참조 객체는 삭제되고 참조 객체는 survivor space로 이동한다. 지난 Minor GC 때 S0으로 이동한 객체들의 경우, 나이를 increment하고 S1으로 이동한다.같은 survivor space에 나이가 다른 객체들이 존재하게 된다.
    • 모든 참조 객체가 S1으로 이동한 후, S0와 Eden space는 clear 된다.
  5. Additional Aging
    gc10
    • 그 다음 Minor GC 때, 같은 과정이 반복된다. 하지만 이번에는 survivor space가 switch 된다. S1에 있던 참조 객체는 나이를 먹으며 S0으로 이동한다. Eden space의 참조 객체도 S0으로 이동한다.
    • 모든 참조 객체가 S0으로 이동한 후, Eden space와 S1은 clear 된다.
  6. Promotion
    gc11
    • Minor GC 이후 특정 나이 threshold (그림 예시에서는 8)에 도달하면 Young 영역에서 Old 영역으로 promotion된다.
  7. Minor GC가 계속됨에 따라 객체들이 Old 영역으로 이동한다.
    gc12
  8. 지속된 Promotion으로 Old 영역이 꽉 차게 되면, Major GC가 수행되어 Old 영역을 clear한다.

 

Young 영역은 일반적으로 Old 영역보다 크키가 작기 때문에 GC가 보통 0.5초에서 1초 사이에 끝난다. 그렇기 때문에 Minor GC는 애플리케이션에 크게 영향을 주지 않는다. 하지만 Old 영역은 Young 영역보다 크며 Young 영역을 참조할 수도 있다. 그렇기 때문에 Major GC는 일반적으로 Minor GC보다 시간이 오래걸리며, 10배 이상의 시간을 사용한다. 참고로 Young 영역과 Old 영역을 동시하 처리하는 GC는 Full GC라고 한다.

 

 


 

 

5. GC의 주요 알고리즘 정리

  1. Mark and Sweep
    • Mark: 참조 가능한 객체를 탐색하고 식별한다.
    • Sweep: 참조되지 않은 객체를 메모리에서 제거한다.
  2. Generational Garbage Collection
  3. Stop-the-World
    • GC를 실행하기 위해 JVM이 애플리케이션 실행을 잠시 멈춘 상태를 말한다. GC가 메모리 관리를 수행하는 동안 GC를 실행하는 스레드를 제외한 모든 스레드들이 중단된다. GC가 안전하게 작업을 완료할 수 있도록 보장힌다. 어떤 GC 알고리즘을 사용하더라도 발생하게 된다. GC 튜닝은 보통 이 Stop-the-World 시간을 줄이는 성능 개선을 뜻한다.

 

 

참조

https://d2.naver.com/helloworld/1329

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

'CS > 자바' 카테고리의 다른 글

Promotion and Casting (자바의 타입변환)  (1) 2024.11.29