Garbage Collection
JVM의 Garbage Collection에 대해서 알아봅니다.
Goal
- JVM의 실행엔진 안에 속해있는 GC에 대해서 알아봅니다.
- GC의 동작방식에 대해서 알아봅니다.
- GC의 알고리즘 종류에 대해서 알아봅니다.
What is GC
사용되지 않는 객체에 대한 메모리 할당을 자동으로 해제 시켜주는 기술을 이야기합니다.
- 기본적으로 Java Heap 영역의 메모리를 다룹니다.
How Working
가비지 컬렉션 과정 - Generational Algorithm
새롭게 생긴 객체는 금방 없어지고, 오래 버틴 객체는 오래 버틴다는것을 기반으로 가져갑니다.
java7

java8

- Heap은 Young영역과 Old영역 으로 메모리를 분할하고, 신규로 생성되는 객체는 Young 영역에 보관합니다.
- Young영역에서 객체가 사라질때를
Minor GC, Old영역에서 객체가 사라질떄를Major GC라고 부릅니다. - Eden space에 객체를 채우다가 가득차면
Minor GC가 발생합니다
Young 영역
- Eden
- Survivor (2개)


- 처음 생성된 객체는 Eden 영역에 위치합니다. Eden 영역이 가득차면 Minor GC가 시작됩니다.

- 먼저 참조된 이력이 있는 객체들은 age를 높여 s0 에 이동을 시키고, 그렇지 않은 객체들은 제거됩니다.

- 또 다음 Minor GC가 일어나면, s0와 Eden에 있던 객체중 참조된 것은 s1으로 이동하고 나머지 공간인 s0과 Eden에 있는 객체들은 제거됩니다.
- s0와 s1는 번갈아가서 반복되기 때문에, s0이 생존공간이 되고 s1, Eden의 객체들이 삭제되는 경우도 있을 수 있습니다.

- 일정 age가 넘어간 객체들은 old 영역으로 이동하게 됩니다.
- 이때 age 기본값은 31입니다. 해당 Age를 기록하는데 사용되는 bit가 6bit이기 때문입니다.
이외의 GC 알고리즘 종류
Reference Counting Algorithm
객체가 참조되어지고 있는 Count가 몇개인지를 확인하고 GC에서 지울지를 결정합니다.
- 0개가 되는 객체들은 메모리해제의 대상이 됩니다.
Mark and Sweep Algorithm
Reference Counting는 순환참조를 해결하지 못한다는 단점이 있습니다. 이를 개선하기 위해 나온 방법입니다.
Root Set로부터 접근 가능한 객체를 전부 Marking 해둡니다. 중복 되지 않게 Flag같은것을 심어둡니다.- Marking되지 않은 객체들의 메모리를 제거합니다.
- 하지만 메모리 중간중간이 비어있는 단편화 현상이 발생합니다.
Mark and Sweep Compaction Algorithm
메모리 단편화 현상을 해결하기 위해 나온 방법입니다.
- sweep 이후 단편화가 발생한 공간을 이어 붙입니다.
- 과거 디스크 모음조각을 하던 시절을 연상하면 기억하기 쉽습니다.
- 하지만 해당 부분을 이어붙이는데 들어가는 오버헤드가 발생합니다.
Copying Algorithm
Heap을 Active영역과 InActive 로 나누어서 관리합니다.
Generational Algorithm의 과거 형태입니다.- 이 알고리즘도 단편화문제를 해결하고자 나온 알고리즘입니다.
- Heap영역을 절반으로 나눈뒤, Active영역에만 메모리를 할당합니다.
- Active 영역이 다 차게되면, 살아남는 객체들은 InActive 영역으로 Copy합니다.
- 이후 Active 영역의 Object들을 삭제합니다.
- Active와 InActive의 위치를 서로 바꿉니다.
- 하지만 힙의 절반영역밖에 쓰지 못하는 단점과, Copy과정에 들어가는 오버헤드가 있습니다.
GC 종류
GC별 동작 방식을 정리한 내용은 글을 분리해서 작성할 예정입니다.
- Serial GCL (mark sweep compact)
- Parallel GC: java8 디폴트 (쓰레드 병렬처리)
- Parallel Old GCL: (Mark Summary Compact)
- CMS: (stop the world는 짧지만, 메모리 CPU 낭비가 심한 GC)
- G1GC: Java11 디폴트 (큰 메모리에 적합한 GC, 이전에는 Heap이 작았기 때문에 순차적으로 접근해도 큰문제가 없었음)
- 기존의 young old 영역의 heap 형태는 잊어야 합니다.
- 영역이 다차면 다른 영역에 객체를 할당하고 GC 진행
- Z1 GC: (Java11 부터 일부 도입)