[Java] Garbage Collection의 동작 원리

Kai·2024년 3월 24일
0

Java

목록 보기
16/22

🤔 Garbage Collection(이하 GC)란?


Java에서 GC는 Heap메모리에 할당됐던 객체들 중에서 더 이상 사용되지 않는 객체들을 메모리에서 제거해주는 기능을 이야기한다.

C언어에서는 메모리에서 데이터를 해제해주는 것을 직접 구현해줘야하지만, Java를 포함해서 최근에 나온 언어들은 대부분 GC를 통해서 자동적으로 메모리 관리를 해준다.

Stop the world와 GC의 성능

오래된 데이터를 메모리에서 제거하는 Full GC가 실행되면, GC가 실행되는 쓰레드 외의 쓰레드들은 모두 일시중지하게 된다. 그래서 잠깐 동안 서비스가 멈추게 되는데, 이를 "Stop the world"라고 일컫는다.
GC의 성능은 이 "Stop the world"를 얼만큼 짧게 만드는지가 관건이라고 할 수 있다.


🧙 Heap영역의 구조와 GC


Heap 메모리 영역은 아래와 같은 구조를 갖고 있다.

Young generation

처음 생성된 객체들이 존재하는 Eden, 한번 이상의 GC에서 살아남은 객체들이 존재하는 Survivor0, Survivor1이 Young generation이라고 불리는 공간이다.

Young generation에서 이루어지는 GC를 Minor GC라고 부르고, Eden영역이 꽉 차면 Minor GC는 실행된다.

GC에서 살아남으면, age값이 1씩 올라가는데, age가 임계치를 넘어가면, Old generation으로 이동하게 된다.

Old generation

Young generation에서도 GC되지 않은 오래된 객체들이 존재하는 영역이 Old generation이고, 여기서 이루어지는 GC는 Major GC 또는 Full GC라고 부르고, Old generation영역이 꽉 차면, Major GC는 실행된다.


🔨 GC의 동작 방식


Mark & Sweep 알고리즘

GC의 알고리즘은 다양하지만, 가장 기본적이면서 대표적으로 Mark, Sweep이라고 일컫어지는 과정을 통해서 GC는 동작한다.

먼저, Mark는 GC는 Heap메모리에 할당된 데이터가 실제로 사용되고 있는 객체인지에 대한 여부를 판단하는 과정이다. 사용되고 있는 데이터라면 Reacheable, 사용되고 있지 않는 객체라면 Unreacheable로 구분한다.

Mark과정에서 감지한 사용되지 않는(Unreacheable) 객체들을 메모리에서 해제하는데, 이 과정을 Sweep이라고 부른다.

이 때, GC에서 살아남은 횟수에 따라서 위에서 이야기한 Heap메모리 내의 영역을 이동하게 되는 것이다.

사용되지 않는 객체인지 어떻게 알까?

Mark라는 과정을 통해서 사용되고 있는 객체인지에 대한 여부를 판단한다고 했는데, 어떤 것을 보고 이 객체가 사용중인지 아닌지 알 수 있을까?

GC는 Root set이라고 불리는 3개의 메모리 영역(Stack, JNI, Method area)들을 기점으로 스캔을 한다.
각각은 Heap에 할당된 객체들을 참조하고 있어서 이 영역들에 존재하는 모든 데이터를 스캔하면, Heap에서 참조되고 있지 않는 객체들을 판별할 수 있는 것이다.

이렇게 참조되고 있는 Reachable데이터와 그렇지 않은 Unreachable데이터를 구분하는 Mark작업이 이루어진다.


🧐 GC의 종류


GC는 그 동작방식 또는 알고리즘에 따라서 다양한 종류가 존재한다. 각각을 한번 알아보자.

1) Serial GC

java -XX:+UseSerialGC -jar Application.java
  • 단일 쓰레드 환경에서 사용하기에 적합한 가장 단순한 GC
  • Minor GC에서는 Mark & Sweep, Major GC에서는 Mark & Sweep & Compact알고리즘을 사용한다.

2) Parallel GC

java -XX:+UseParallelGC -jar Application.java
  • Java5 ~ Java8에서 기본 GC이다.
  • Serial GC와 동일한 알고리즘을 사용하지만, GC가 병렬로 이루어진다는 특징이 있어서 비교적 빠른 Stop the world시간을 갖게 된다.

3) G1 GC

java -XX:+UseG1GC -jar Application.java
  • Java9이후에서 기본 GC이다.
  • 4GB이상의 큰 Heap메모리 용량이 확보 가능한 경우 사용할 것을 권장한다.
  • Young/Old generation이라는 물리적인 공간으로 영역을 구분하던 클래식한 방법을 탈피하였다. 대신, Region이라는 동적 메모리 공간이라는 개념을 도입해서, 효율적으로 메모리 공간을 확보하면서도 빠르고 적은 빈도의 GC성능이 보장된다.

📌 오라클 공식문서

4) Z GC

java -XX:+UseZGC Application.java
  • Java15부터 사용 가능한 GC이다.
  • G1 GC의 Region처럼 동적 메모리 공간을 의미하는 ZPage라는 개념이 존재한다.
  • Region과 ZPage의 차이점은 Region은 그 크기가 고정되어 있는 것과 달리 ZPage는 2MB의 배수로 동적인 크기를 가질 수 있다.
  • Heap크기에 무관하게 10ms이하의 Stop the world 시간을 보장한다고 이야기하고 있다.
  • 이론상으로는 독보적으로 좋은 성능의 GC이지만, 출시된지 얼마되지 않았다보니 기본 GC로 채택되어 있지는 않다.

🙏 참고


0개의 댓글