JVM의 Garbage Collection의 경우, Stop-The-World가 발생하여 시스템 전체 성능에 영향을 줄 수 있다.
특히, Major GC의 경우 Minor GC에 비해 오랜 시간이 걸리므로 이에 대한 최적화가 필요하다.
이를 극복하기 위해, 다양한 GC 알고리즘이 지속적으로 개발되어 왔다.
Serial GC
- CPU 코어가 1개일 때 사용하기 위한 GC 알고리즘
- GC를 처리하는 쓰레드가 1개이다. 따라서 멀티 코어 환경에서는 절대 사용하면 안된다.
- Minor GC에는 mark-and-sweep, Major GC에는 Mark-Sweep-Compact를 이용한다.
Parallel GC
- Java 8에서 default GC로 채택되었다.
- Serial GC와 다르게 Minor GC를 멀티 스레드로 수행한다.(Major GC는 동일)
- 옵션을 통해 애플리케이션의 최대 지연 시간 또는 GC를 수행할 쓰레드의 개수 등을 설정할 수 있다.
Parallel Old GC
- Parallel GC를 개선한 버전
- Parallel GC에서 싱글 스레드로 수행했던 Major GC를 멀티 스레드로 수행 가능하게 개선
- Mark-Summary-Compact 방식이 등장하였다.
- Sweep은 단일 스레드가 Old 영역을 Full Scan하여 Reachable 객체만 찾는 과정이다.
- 반면 Summary는 여러 스레드가 Old 영역을 분리하여 Scan한다.
CMS GC(Concurrent Mark Sweep)

- 어플리케이션 스레드와 GC 스레드를 동시에 실행하여 stop-the-world 시간을 최대한 단축하고자 하였다.
- 시스템이 실행 중일 때, 프로세서의 자원을 공유하여 이용 가능해야 한다.
- 다른 GC 방식 대비 CPU, 메모리 자원이 더 소요된다.
- Compaction 단계를 수행하지 않아 메모리가 파편화되는 문제가 있다. (결과적으로 Compaction 단계가 수행되면 Stop-The-World 시간이 길어진다)
- Java9에 deprecated 되었고 Java 14에서 삭제되었다.
G1 GC (Garbage First)

- 대용량 메모리가 있는 다중 프로세서 시스템을 대상으로 함 (4GB 이상의 heap 메모리 & Stop-The-World 시간 0.5초)
- Java7에서 최초 release되었고, Java9+ 버전의 default로 지정되었다.(현재까지도 default GC이다.)
- 기존 Heap 영역을 고정된 Young/Old 영역으로 나누어 사용하였지만, G1 GC에서는 Region이라는 개념을 새로 도입해서 사용하였다. Region의 크기는 서로 동일하며, 가비지가 많은 Region을 스캔하여 우선적으로 GC를 수행하는 것이 핵심이다.
G1 GC의 Minor GC
한 Region에 객체를 할당하고, 해당 지역이 꽉 차면 다른 지역에 객체를 할당하며 Minor GC를 수행한다.
가비지가 가장 많은 지역을 찾아서 Mark-Sweep을 수행한다.
만약 복제되는 지역이 unused 지역이라면(사진 상에서 회색 바탕의 빈 공간에 할당되는 경우) 해당 지역은 Survivor 영역이 되고, 기존 Eden 영역은 unused Region이 된다.
G1 GC의 Major GC
시스템 운영 과정에서 객체가 너무 많아 메모리를 빠르게 회수할 수 없을 때 실행된다.
기존의 다른 GC 알고리즘은 모든 Heap 영역에서 GC가 수행되어 처리 시간이 오래 걸렸다.
하지만, G1 GC는 각 Region별로 가비지를 추적하고 있기 때문에 GC를 수행할 지역에 한해서만 진행하며,
이러한 작업을 Concurrent하게 수행하기 때문에 애플리케이션의 지연도 최소화할 수 있다.
ZGC

- Java 15 release
- 대량의 메모리(MB~16TB)를 low-latency로 처리하기 위해 디자인 된 GC
- ZGC는 ZPage라는 영역을 사용하며, G1 GC와 다르게 ZPage는 2^n MB로 동적으로 운영된다.
- 따라서 힙 크기에 상관없이 10MS 미만의 일정한 Stop-The-World 시간을 보장할 수 있다.
- 기존 애플리케이션 쓰레드와 병렬적으로 수행될 수 있다.
- 여러 부분으로 분할되고 여러 스레드에서 실행되며 동시 압축된다. 이는 G1 GC와의 차별점이다.
ZGC가 low-latency를 보장하며 G1 GC 대비 성능이 훨씬 좋은 것 같은데, 왜 ZGC가 Default GC가 되지 못했을까?
- 대규모 힙 메모리를 효과적으로 처리하지만, 소규모 힙에서는 메모리 오버헤드가 발생할 수 있다.
- low-latency를 보장하나 모든 환경에서 low-latency를 보장할 필요는 없다.
- 비교적 최근에 release되었고, 모든 버전에 대해 안정적이며 호환성이 높은 GC는 G1 GC라고 판단되어 현재 default GC는 G1 GC가 채택되고 있다.
References
- https://d2.naver.com/helloworld/0128759
- https://velog.io/@akfls221/JVM%EC%9C%BC%EB%A1%9C-%EC%8B%9C%EC%9E%91%ED%95%B4-GC-%EA%B7%B8%EB%A6%AC%EA%B3%A0-GC-%ED%8A%9C%EB%8B%9D%EA%B9%8C%EC%A7%80#gc-alogorithm
- https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98GC-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC
- https://d2.naver.com/helloworld/1329
- https://mangkyu.tistory.com/119
'CS > Java' 카테고리의 다른 글
[Java] Garbage Collection(GC)의 동작 원리 (0) | 2024.06.24 |
---|---|
Java의 Collections Deep Dive - 1 : HashMap이란? (0) | 2024.05.17 |
@Override가 뭐야? (0) | 2023.03.29 |
[자바] 인터페이스는 객체지향의 4대 특성중에 무엇을 지니는가? (1) | 2023.03.28 |
[자바] 객체지향의 4가지 특성 (0) | 2023.03.28 |