본문 바로가기
Spring

JVM GC의 종류(Serial, Parallel, CMS, G1 GC)

by jinukix 2021. 10. 1.

GC (Garbage Collector)

JVM이 자동으로 메모리를 관리해주기 때문에 개발자는 메모리를 처리하기 위한 로직을 작성하지 않아도 된다. 하지만 GC를 수행하는 시점에 Stop the World가 발생하게 되고 애플리케이션이 중지되는 현상이 일어난다. GC가 많이 일어날수록 애플리케이션 성능에 많은 영향을 끼치게 된다. 그렇기 때문에 우리는 GC가 어떻게 동작하는지 이해할 필요가 있다.

GC의 동작은 다음과 같이 이야기할 수 있다.

1. Heap 영역에 존재하는 객체들에 대해 접근 가능한지 확인한다.
2. GC Root(Stack 참조 변수, static 영역 데이터, JNI 객체)부터 시작해 참조값을 따라가 접근 가능한 객체를 Mark한다.
3. Mark 되지 않은 객체. 즉, 접근할 수 없는 객체는 제거(Sweep) 대상이 된다.

출처: https://d2.naver.com/helloworld/329631

1. Serial GC (-XX: +UseSerialGC)

가장 단순한 방식의 GC이며, 싱글 스레드로 동작한다. 싱글 스레드로 동작하기 때문에 느리다. (Stop the World의 시간이 길다) Young 영역에서는 Mark Sweep 알고리즘으로 GC가 수행된다. Old 영역에서는 Mark Sweep Compact 알고리즘으로 동작하며, Compact는 필요 없는 객체들을 지우고 살아있는 객체들을 한 곳으로 모으는 작업이다.

2. Parallel GC (-XX: +UseParallelGC)

Java 8의 Default GC이며 throughput collector라고도 알려진 방식이다. Young 영역의 GC를 멀티 스레드 방식으로 처리하기 때문에 Serial GC에 비해 상대적으로 빠르게 동작한다. Old 영역은 마찬가지로 Mark Sweep Compact 알고리즘으로 동작한다. Parallel Old GC를 사용한다면 Old 영역까지 멀티스레드 방식으로 처리할 수 있다.

3. CMS GC (-XX: +UseConcMarkSweepGC)

CMS (Concurrent Mark Sweep) GC는 Stop the World로 애플리케이션이 멈추는 현상을 줄이는 목적으로 나온 GC이다. Young 영역에 대한 GC는 병렬 콜렉터와 동일하다. Old 영역은 다음과 같이 동작한다.

1. Mark: GC Root가 참조하는 객체만 마킹. (Stop the World 발생)
2. Concurrent Mark: 참조하는 객체를 따라가며 지속적으로 마킹. (Stop the World 없이 동작)
3. Remark: Concurrent Mark과정에서 변경된 사항이 있는지 다시 한번 마킹하며 확정하는 작업. (Stop the World 발생)
4. Concurrent Sweep: 마킹되어 있는 객체들을 제거하는 단계 (Stop the World 없이 동작)

하지만 CMS GC는 다른 GC 방식보다 메모리와 CPU를 더 많이 필요하며, Compact 단계를 거치지 않기 때문에 메모리 단편화가 발생할 수 있다.

3. Garbage First GC (-XX: +UseG1GC)

Java 9+ Default GC이다. 기존의 GC 알고리즘은 Heap 영역을 물리적으로 Young(Eden영역, Survivor 영역)과 Old 영역으로 나눠 사용했지만, G1 GC는 Eden 영역에 할당하고, Survivor로 카피하는 등의 과정을 거치지만 물리적으로 메모리 공간을 나누지 않는다. 대신 Region이라는 개념을 새로 도입해 Heap을 균등하게 여러 Region으로 나누고 각 지역을 역할과 함께 논리적으로 구분(Eden, Survivor, Old 인지)하여 객체를 할당한다. G1 GC는 Eden, Survivor, Old 역할에 더해 Humongous, Available/Unused의 두 역할을 추가했다.

Humongous: Region 크기의 50%를 초과하는 객체를 저장하는 Region.
Available/Unused: 사용되지 않은 Region.

G1 GC의 핵심은 Heap을 동일한 크기의 Region으로 나누고 전체 Heap을 탐색하지 않고 가비지가 많은 Region에 대해 우선적으로 GC를 수행하는 것이다. 

'Spring' 카테고리의 다른 글

JDK Dynamic Proxy vs CGLIB  (0) 2021.11.23
@Transactional  (0) 2021.11.23
JPA - 영속성 컨텍스트  (0) 2021.10.01
MySQL - 파티셔닝  (0) 2021.10.01
JPA - OSIV (Open Session In View)  (0) 2021.09.30

댓글