[JAVA] Serial GC, Parallel GC, Parallel Old GC 동작 원리
Garbage Collector란?
Garbage Collector는 대부분의 객체는 금방 접근 불가한 상태가되고, 오래된 객체가 젊은 객체를 참조하는 일은 아주 적게 존재한다는 'weak generational hypothesis'를 전제로 만들어졌다. Garbage Collector는 JVM의 runtime data area의 heap영역중 참조되고 있지 않는 객체를 데몬 스레드를 통해 제거한다. STW(stop-the-world)는 GC실행을 위해 애플리케이션이 멈추는 것을 의미한다. 대부분 GC알고리즘의 목표는 STW의 시간을 최소화하는 것이다.
GC의 동작 과정
Hotspot VM의 heap영역은 young generation과 old generation영역으로 구분된다.
young generation
minor gc가 발생하는 영역으로 eden, survivor1, survivor2영역이 존재한다.
old generation
young generation에서 몇 차례 살아남은 객체가 존재하는 영역이다. major gc(full gc)가 발생하는 영역으로 old영역이 존재한다.
metaspace / permanent generation /
permanent generation은 jdk8버전부터 삭제되고 metaspace영역으로 대체되었다.
permanent는 heap영역에 속해 jvm에 의해 관리되는 영역이었다.
metaspace는 native memory영역으로 os에 의해 관리되는 영역이다.
기존의 permanent영역은 jvm에 의해 크기가 강제되었기 때문에 out of memory의 이슈가 존재했다.
meta space는 os에서 사용가능한 메모리 영역을 사용할 수 있다.
기존에 permanent영역에서 저장되던 클래스, 메서드의 메타정보, static 변수 등은 metaspace에 저장된다.
Minor GC의 동작 과정
- 객체가 새롭게 생성되면 eden영역에 메모리가 할당된다.
- eden영역이 가득차면 minor gc가 동작한다. eden영역의 객체중 살아있는 객체는 suvivor1영역으로 copy되고, eden영역의 메모리는 비워진다.
- 다시 eden영역이 가득차면 minor gc가 동작한다. eden영역과 survivor1영역의 객체중 살아있는 객체는 survivor2영역으로 copy되고, eden영역은 비워진다.
- eden영역이 가득찰 때마다 survivor1, 2를 옮겨가며 minor gc가 반복된다. survivor영역을 이동하는 이유는 메모리 단편화를 방지하기 위해서이며, 살아남은 횟수는 age bit에 기록되고 threshold를 넘기거나 survivor영역의 메모리가 부족해지는 경우 old영역으로 이동한다.
Major GC의 동작 과정
Serial GC
serial gc는 mark-sweep-compact알고리즘을 사용한다.
- mark단계에서는 old영역에서 살아있는 객체를 확인한다.
- sweep단계에서는 heap영역의 앞부분부터 확인하여 표시된 객체를 제거한다.
- compact단계에서는 메모리 단편화를 방지하기위해 힙의 앞부분부터 객체를 채워 넣는다.
serial gc는 메모리가 적고 코어 수가 적을 때 적합하다.
Parallel GC
parallel gc는 기본적으로 serial gc와 동작과정은 동일하지만, minor gc에서 사용되는 thread의 수를 늘릴 수 있다. java8버전에서 default로 사용되는 gc이다.
parallel gc는 메모리가 충분하고 코어 수가 많을 때 효과적이다.
Parallel Old GC
parallel old gc는 parellel gc와 비교하여 old영역이 처리되는 방식이 다르다. parallel old gc는 mark-summary-compact방식을 사용한다. mark-sweep-compact방식은 단일 스레드가 old영역을 검사하는 방식이라면 mark-summary-compact방식은 여러 스레드를 사용해서 old영역을 탐색한다.
- mark단계에서는 old영역을 region별로 나누고 region별로 살아있는 객체를 식별한다.
- summary단계에서는 region별 통계정보로 살아있는 객체의 밀도가 높은 부분이 어디까지 인지 dense prefix를 정한다. 오랜 기간 참조된 객체는 앞으로 사용할 확률이 높다는 가정하에 dense prefix를 기준으로 compact영역을 줄인다.
- compact단계에서는 compact영역을 destination과 source로 나누며 살아있는 객체는 destination으로 이동시키고 참조되지 않는 객체는 제거한다.