가비지 컬렉터는 더 이상 사용되지 않는 객체를 탐지하고 가비지 컬렉션 과정을 수행하는 JVM 내부의 실행 주체다.
어떤 객체가 계속 사용 중인지 추적한다. (객체가 더 이상 참조되지 않으면 사용되지 않는 것으로 간주한다.)
더 이상 사용되지 않는 객체의 메모리를 해제하여 다른 객체가 사용할 수 있도록 한다.
Mark and Sweep은 GC Root로부터 도달 가능한 객체를 먼저 표시하고, 표시되지 않은 객체를 제거하는 가비지 컬렉션 알고리즘이다.
가비지 컬렉션의 대상은 다음과 같은 기준으로 판별된다.
Reachable (도달 가능): 객체가 하나 이상의 변수에 의해 참조되고 있는 상태다.
-> 가비지 컬렉션 대상 X
Unreachable (도달 불가능): 객체가 더 이상 어떤 변수에도 참조되지 않은 상태다.
-> 가비지 컬렉션 대상 O

Mark 과정:
Sweep 과정:
Compact 과정:
Root Space: method area, static 변수, stack, native method stack

JVM의 힙 영역은 처음 설계될 때 다음 2가지를 전제로 설계되었다.
-> 객체는 대부분 일회성이고 메모리에 오랫동안 남아있는 경우는 드물다
이러한 특성을 이용해 JVM 개발자들은 효율적인 메모리 관리를 위해, 객체의 생존 기간에 따라 물리적인 힙 영역을 나누게 되었고 Young과 Old 이렇게 2가지 영역으로 설계했다.

Young 영역은 새로 생성된 객체가 할당되는 영역이다.
대부분의 객체가 금방 Unreachable상태가 되기 때문에 많은 객체가 Young 영역에 생성됐다가 사라진다.
Young 영역에 대한 가비지 컬렉션을 Minor GC라고 부른다.
Old 영역은 Young 영역에서 Reachable상태를 유지해서 살아남은 객체가 승격되어 저장되는 영역이다.
Young 영역보다 크게 할당되고, 가비지는 적게 발생한다.
Old 영역에 대한 가비지 컬렉션을 Major GC라 하고, 힙 전체를 대상으로 수행되는 GC를 Full GC라고 한다.
Old 영역이 Young 영역보다 크게 할당되는 이유는 Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않는다. 그리고 장시간 살아남는 객체가 누적되서 더 큰 공간이 필요하고, 큰 객체들은 Young 영역이 아니라 Old영역에 할당되기 때문이다.
힙 영역은 효율적인 GC를 위해 Young 영역을 3가지 영역(Eden, survivor 0, survivor 1)으로 나눈다.

Eden에는 새로 생성된 객체가 위치한다.
정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor 영역으로 보낸다.
Survivor 0 / Survivor 1은 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역이다.
Survivor 0 또는 Survivor 1 둘 중 하나는 꼭 비어 있어야 하는 규칙이 있다.

처음 생성된 객체는 Eden영역에 위치한다.
그러다 객체가 계속 생성되어 Eden 영역이 꽉차면 Minor GC가 실행된다.
Minor GC가 실행되면 Mark 동작을 통해 Reachable 객체를 탐색한다.
Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동한다.
그리고 Eden 영역에서 사용되지 않는 객체의 메모리를 해제한다.
살아남은 모든 객체들은 age값이 1씩 증가한다. (age값이 임계값에 다다르면 Promotion(Old 영역으로 이동) 여부를 결정한다.)
다시 Eden 영역에 객체들이 꽉 차면 Minor GC가 발생한다. (반복)
객체의 age가 임계값(여기선 8로 설정)에 도달하게 되면
이 객체들은 Old 영역으로 이동된다. 이를 promotion이라 부른다.
위의 과정이 반복되어 Old 영역의 공간이 부족하게 되면 Major GC가 발생된다.
Old 영역은 Young 영역에 비해 상대적으로 큰 공간을 가지고 있어서 이 공간에서 메모리 상의 객체 제거에 많은 시간이 걸리게 된다. (Young 영역의 10배 이상의 시간 사용)
-> Stop-The-World 문제 발생 (GC가 동작하는 동안 다른 동작을 멈춰서 오버헤드가 발생하는것)
그래서 자바 개발자들이 계속해서 가비지 컬렉션 알고리즘을 발전시켜왔다.
가비지 컬렉션 알고리즘 종류를 알아보자
자바가 발전됨에 따라 힙의 사이즈가 커지면서 애플리케이션 지연 현상이 두드러지게 되었고, 이를 최적화하기 위해 다양한 가비지 컬렉션 알고리즘이 개발되었다.

Serial GC는 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 GC다.
GC를 처리하는 쓰레드가 1개여서 가장 Stop-The-World 시간이 길다. (보통 실무에서 안 씀)
Parallel GC는 Java 8의 디폴트 GC다.
Serial GC와 기본적인 알고리즘은 같지만, Young 영역의 Minor GC를 멀티 쓰레드로 수행한다. (Old 영역은 싱글 쓰레드)
Parallel Old GC는 Parallel GC를 개선한 버전이다.
Young 영역 뿐만 아니라, Old 영역에서도 멀티 쓰레드로 GC를 수행한다.
Mark-Summary-Compact 방식 이용
CMS GC는 어플리케이션의 쓰레드와 GC 쓰레드가 동시에 실행되어 Stop-The-World 시간을 최대한 줄이기 위해 고안된 GC다.
GC 과정이 매우 복잡해졌고, 메모리 파편화 문제같은것 때문에 Java 9 버전부터 deprecated 되었고 Java 14에서는 사용이 중지됐다.
G1 GC는 CMS GC를 대체하기 위해 jdk 7버전에서 최초로 release된 GC다.
Java 9+버전의 디폴트 GC로 지정되었다.
기존 GC 알고리즘에서는 힙 영역을 물리적으로 고정된 Young / Old 영역으로 나누어 사용했지만, G1 GC는 이런 개념과 아예 다른 Region이라는 개념을 새로 도입하여 사용한다.
전체 힙 영역을 Region이라는 영역으로 체스같이 분할하여 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여한다.
-> 가비지로 가득찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어드는 효과를 얻게 되는 원리.

Shenandoah GC는 Java 12에 release된 GC다.
레드 햇에서 개발했고, 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결했다.
강력한 Concurrency와 가벼운 GC 로직으로 힙 사이즈에 영향을 받지 않고 일정한 pause 시간이 소요된다.
Z GC는 Java 15에 release된 GC다.
대량의 메모리를 low-latncy로 잘 처리하기 위해 디자인 된 GC다.
G1의 Region처럼, Z GC는 ZPage라는 영역을 사용하고, G1의 Region은 크기가 고정인데 비해 ZPage는 2mb 배수로 동적으로 운영된다.
힙 크기가 증가해도 Stop-The-World 시간이 절대 10ms를 넘지 않는다.

https://velog.io/@mirrorkyh/GC-%EC%A2%85%EB%A5%98%EC%99%80-%ED%8A%B9%EC%A7%95