Garbage Collector
더 이상 참조되고 있지 않은 (메모리 공간을 낭비하고 있는) 객체들을 치워버리는 친구이다.
이 친구 덕분에 Java
에서는 C
에서처럼 수동으로 메모리를 할당해제 할 필요가 없어졌다.
Garbage Collecting
Heap 영역에서 참조되고 있지 않는 객체들의 메모리를 할당해제하는 과정이다.
영역에 따라 Minor GC, Major GC로 나뉜다.
System.gc() 메소드로 GC를 실행할 수 있지만 제발 하지 말자. 더 똑똑한 사람들이 이미 최적화를 해놓았다.
GC에서 중요한 개념은 2가지가 있다.
Reachability
Stop-the-world
Reachability
- GC에서 객체가 Garbage인지 판별하는 개념이다.
- 유효한 참조가 없으면 reachable.
- 유효한 참조의 최초 셋을 Root set이라 한다.
- Heap 영역 내부의 객체들이 java Stack, native Stack 등에서 참조된다면 reachable.
불필요한 데이터는 명시적으로 null을 대입해 GC 대상으로 만들어 메모리 효율을 높이자.
Stop-the-world
- GC를 수행하기 위해 JVM이 앱 실행을 멈추는 것을 뜻한다.
- GC 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 대기한다.
- Stw가 길면 그만큼 작업 효율이 떨어진다.
- 어떤 GC 알고리즘을 사용해도 근본적으로 stw를 없애지는 못한다.
- GC튜닝이란 이 stw 시간을 줄이는 것을 의미한다.
GC 기본 알고리즘
원리는 대강 이렇다.
- Root set으로부터 참조된 객체를 mark

- mark 없는 객체는 메모리에서 sweep

- Fragmentation 발생

- Mark & Compact Algorithm : sweep 시 메모리 해제한 후 compact (메모리 조각 모음이라고 생각하면 됨)해서 fragmentation을 해결.

Major GC & Minor GC
이거에 대해 알려면 일단 Heap 구조를 알아야 할 필요가 있다.

- Eden : 새로 생성된 객체가 저장되는 공간
- Survivor Spaces : Minor GC에서 살아남은 객체들이 저장되는 공간. S0/S1 둘 중 하나는 반드시 빈 공간이어야 한다.
- Old : 객체용 노인정
Eden + Survivor Spaces를 묶어 Young gen, Old 영역은 Old gen이라 한다.
Minor GC
Young Generation에서 발생한다.
Eden이 꽉 차면 발생하게 되는데,
- 사용되지 않는 객체의 메모리를 해제하고
- Eden영역에 존재하는 객체는 Survival 영역으로 이동한다
Survivor spaces에서 어느 정도 시간이 지면 Promotion 되어 Old 영역으로 옮겨진다.
Major GC
Old Generation에서 발생한다.
Promotion된 객체로 인해 Old gen의 메모리가 부족하면 발생하게 되는데,
영역 크기만 봐도 Old 영역이 Young gen을 합친 것보다 크기 때문에 Minor GC보다 오래 걸린다.
GC 방식들
- Serial GC : 32비트 싱글 쓰레드 앱에서 사용. 싱글 쓰레드라 느림. WAS에 쓰면 ㅈ됨
- Parallel GC: 멀티 쓰레드라 좀 빠르지만 여전히 stw가 문제
- CMS GC : 단계를 늘려 stw 시간을 줄인다. Initial Mark -> Marking/Pre-Cleaning(non stw) -> Remark -> Sweep/Reset(non stw)
- G1 GC : jdk9 이후 기본적인 GC. 메모리를 Region별로 나누고, 각 Region별로 GC를 실행하는 것이 포인트.