Garbage Collection(GC)이란?
유효하지 않은 메모리를 제거하는 것
C언어처럼 메모리 관리가 코드 레벨에서 이루어지는 경우에는 개발자가 직접 free()
함수를 호출해 메모리를 해제해준다. 그러나 자바에서는 개발자가 아닌 JVM내의 가비지 컬렉터가 불필요한 메모리를 알아서 정리해준다. 이 과정을 가비지 컬렉션이라고 한다.
GC의 동작 방식
JVM의 GC는 Mark And Sweep 방식으로 진행한다.
- Mark: GC Roots 안의 모든 변수를 스캔하며 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다.
- Sweep: 마킹되지 않은 객체(Unreachable Objects)를 메모리에서 제거한다.
- Compact: Sweep 후 메모리 안에서 분산된 객체들을 Heap 영역의 시작 주소로 모아 할당된 부분과 그렇지 않은 부분으로 나눈다.
이 과정을 통해 더이상 참조되지 않는 객체를 Heap 메모리에서 제거한다.
Minor GC
Heap 메모리 중 Young Generation에서 일어나는 GC를 말한다.
Young Generation
- 새롭게 생성된 객체가 할당(Allocation)되는 영역이다.
- 대부분의 객체가 금방 참조되지 않는 Unreachable 상태가 되기 때문에 Young Generation 안에 생성되었다가 사라진다.
- 하나의 Eden 영역과 두 개의 Survival 영역으로 나뉘는데 각 영역이 가득찰 때마다 Minor GC가 진행된다.
Minor GC 과정
- Eden 영역이 가득 차면 Minor GC가 수행되고, 참조되지 않은 객체는 제거되고, 사용 중인 객체는 Survivor 영역으로 옮겨진다.
- Survivor 영역이 가득 차면 이 Survivor 영역에서 살아남은 객체를 다른 Survivor 영역으로 옮긴다.
- 이러한 과정을 반복하여 계속 생존한 객체는 Old Generation으로 옮겨진다. 이를 Promotion이라고 한다.
Aging(에이징)
GC를 진행할 때마다 살아남은(?) 횟수를 기록하는 것
Minor GC를 실행하며 Age가 특정 임계점에 도달하면 Promotion이 이루어진다.
Major GC
Heap 메모리 중 Old Generation에서 일어나는 GC를 말한다.
Young 영역에서 Minor GC가 일어나면서 객체의 에이징이 진행되는데, 특정 에이지에 도달한 객체는 Old Generation으로 이동하게된다. 이 과정을 Promotion이라고 한다.
이 과정이 반복되며 Old Generation 마저 가득차게 되면 발생하는 GC가 바로 Major GC이다.
Old Generation
- Young Generation에서 Reachable 상태를 유지하여 생존한 객체가 이후에 복사되는 영역이다.
- Young Generation보다 크게 할당되며, 영역의 크기가 큰 만큼 Garbage는 적게 발생한다.
GC가 두 영역으로 나뉘어서 실행되는 이유
JVM Heap 영역 설계 당시의 두 가지의 전제 때문이다.
- 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
- 오래된 객체가 새로운 객체를 참조하는 일은 드물다.
즉, 객체는 대부분 일회성이며, 메모리에 오랫동안 남아있는 경우는 드물다는 결론이다.
이 전제 의해서 보다 효율적으로 메모리를 관리하기 위해 GC를 수행하는 영역이 두 개로 나뉘게 되었다.
Stop The World
GC를 실행하기 위해 JVM이 애플리케이션의 실행을 멈추는 것
GC를 실행하는 쓰레드를 제외한 모든 쓰레드의 작업이 중단된다.
이 시간을 최적화하기 위해 다양한 GC가 등장하게 되었다.
GC의 종류
Serial GC
- GC를 수행하는 쓰레드가 1개이다.
- 다른 GC에 비해 stop-the-world 시간이 길다.
Parallel GC
- GC를 수행하는 쓰레드가 여러 개이다.
- 가비지 컬렉션이 여러 쓰레드에서 병렬로 실행되는 것
- Java 8 버전의 기본 GC 방식이다.
CMS(Concurrent-Mark-Sweep) GC
- GC 과정을 어플리케이션 쓰레드와 동시에(Concurrently) 수행함으로서 stop-the-world 시간을 최소화하기 위해 고안된 방식이다.
- Compact 과정이 없어서 메모리 파편화 문제가 있다.
- G1 GC가 등장함에 따라 이 방식은 권장되지 않는다.
G1(Garbage First) GC
- CMS GC를 개선한 방식으로 Java 9+ 이상의 기본 GC이다.
- Heap 영역을 일정 크기의 Region으로 나누어 어떤 영역은 Young Gen, 어떤 영역은 Old Gen으로 사용한다.
- 런타임에 G1 GC가 필요에 따라 영역별 Region 개수를 튜닝한다.
참고 자료