일명 GC는 자바의 메모리 관리 방법 중의 하나로 JVM의 Heap영역에서 동적으로 할당했던 메모리 중 필요없어진 메모리 객체를 모아 주기적으로 제거하는 프로세스를 말합니다.
C, C++언어는 이러한 가비지 컬렉션이 없어 수동으로 메모리의 할당과 해제를 일일이 설정해야 하고,
Java이외에도 Python / Go / JavaScript 등 많은 프로그래밍 언어에서 GC가 기본으로 내장되어있습니다.
GC는 특정 객체가 처리되어야 하는지 아닌지 판단하기 위해서 "도달성", "도달능력"이라는 개념을 적용하여 판단합니다.
객체에 Reference가 있다면 Reachable로 분류하고, 객체에 유효한 Reference가 없다면 Unreachable 로 분류해 수거를 진행합니다.
class Main {
public static void main(String[] args) {
String str = new String("Hello GC");
str = null; // 더 이상 참조되지 않음 → GC 대상
System.gc(); // GC 요청 (실제 동작 보장 X)
}
}
Java의 GC 알고지르즘은 크게 3단계로 동작하게 됩니다.
대상이 될 객체를 식별(Mark) 후 제거(Sweep)하고 객체가 제거되어 파편화 된 메모리 영역을 채워나가는 작업(Compack)를 진행합니다.
Mark
reachable
과 Unreachable
를 판단하는 단계Sweep
Compack(압축단계, 필요시 설정을 통해 수행하게됨)
Java Heap은 GC 성능 최적화를 위해 생성된 상황에 맞춰 분류를 진행하게 됩니다.
Young / Old Generatin, Measpace로 구분합니다.
Young영역보다 Old영역이 더 크게 할당되는 이유는 Young영역은 수명이 짦은 객체들이 주로 가기 때문에 GC가 활발하게 동작하지만 Old영역의 경우에는 큰 객체 or 수명이 긴 객체들이 존재하기 때문에 보다 큰 영역을 차지하고 있습니다.
[!NOTE]
Young영역을 세부적으로 분류하면 다음과 같습니다.
- Eden : 새롭게 생성된 객체가 저장되는 공간
- Survivor S0, S1 : Eden에서 살아남은 객체가 이동하는 영역.
Young영역에서 살아남은 객체가 저장되는 영역.
- Young영역보다 크게 할당되며 영역의 크기가 큰 만큼 GC는 적게 발생함.
Old영역이 가득 차게 되면 GC가 발생하여 메모리를 정리함.
- Old영역의 GC는 Major / FUll GC라고 명칭하기도 함.
GC를 수행하기위해서는 Stop The World
가 발생하게 되고 이로 인해 애플리케이션이 중지되는 문제점이 발생하게 되었습니다. 또한 자바의 발전으로 Heap영역이 커지면서 지연현상이 두드러지게되었고 이로인해 GC의 다양한 알고리즘이 개발되게 되었습니다.
STW - Stop the World
GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미합니다.
GC가 동작하는 동안 GC관련 Thread를 제외한 모든 Thread를 중지하게 되어 서비스 이용에 차질이 생길 수 있습니다.
/ms
이내의 지연시간을 목표로하는 GC로 JDK 11이후에 나옴.JDK 21 ~ 23버전에서 사용중인 GC 알고리즘은 G1 GC를 사용하고 있습니다.
JDK 21이후에 Generational ZGC가 생겨났지만 아직까지는 기본 GC로 설정되어 있지는 않다고합니다.