가비지 컬렉션(Garbage Collection)
가비지 컬렉션은 프로그래밍에서 더 이상 사용하지 않는 메모리, 즉 "쓰레기"가 된 메모리를 자동으로 회수하여 재활용하는 프로세스이다. 이는 개발자가 명시적으로 메모리를 해제해야 하는 부담을 덜어주고, 메모리 누수와 같은 문제를 예장하는 데 중요한 역할을 한다.
가비지 컬렉션의 기본 원리
가비지 컬렉션의 핵심 원리는 어떤 메모리 객체가 아직 사용되고 있는지, 아닌지를 판단하고 사용되지 않는 객체가 차지하고 있는 메모리를 회수하는 것이다.
가비지 컬렉션의 기본 원리는 다음과 같다.
- 객체 추적 : 가비지 컬렉터는 프로그램 내의 모든 객체를 추적하고 관리한다. 각 객체가 어떤 변수나 다른 객체에 의해 참조되고 있는지 여부를 파악한다.
- 도달 가능성 판단 : 가비지 컬렉터는 특정 객체로부터 프로그램의 실행 시작점까지의 참조 경로가 존재하는지 확인한다. 만약 참조 경로가 있다면 해당 객체는 "도달 가능" 하다고 판단하고, 그렇지 않다면 "도달 불가능" 하다고 판단한다.
- 메모리 회수 : 도달 불가능하다고 판단된 객체들은 더 이상 프로그램에서 사용될 수 없으므로, 가비지 컬렉터는 이들이 차지하고 있던 메모리 공간을 회수하여 다른 객체에게 할당될 수 있도록 한다.
주요 가비지 컬렉션 방식
- Mark and Sweep
먼저 모든 객체를 "사용 안 함"으로 표시한 후, 루트 객체부터 시작하여 도달 가능한 객체들을 "사용 중"으로 표시한다. 이를 Mark라고 표현한다. 이후 "사용 안 함"으로 표시된 객체들의 메모리를 회수 한다. - Mark And Compact
Mark and Sweep과 유사하게 도달 가능한 객체를 표시한 후, 회수되지 않은 객체들을 메모리의 한쪽 영역으로 이동시켜 메모리 단편화를 줄인다. - Copying Collection
메모리를 두 개의 영역으로 나누어 사용한다. 한 영역이 꽉 차면, 살아있는 개체들을 다른 영역으로 복사하고, 기존 영역의 모든 메모리를 해제한다. - Generational Collection
객체의 생존 주기에 따라 메모리 영역을 나누어 관리한다. 대부분의 객체는 금방 사라진다는 가정하에, 젋은 객체 영역에 대해 더 자주 가비지 컬렉션을 수행한다.
주요 가비지 컬렉터 종류 및 차이점
Serial GC
- 가장 기본적인 GC 알고리즘으로, Young Generation과 Old Generation 모두에서 단일 스레드를 사용하여 GC를 수행한다.
- GC 수행 중에는 모든 애플리케이션 스레드가 멈추는 Stop-The-World(STW) 현상이 발생한다.
- 작은 힙 크기를 가진 환경이나 CPU 코어가 적은 환경, 개발 환경 등에서 적합하며, 프로덕션 환경에서는 일반적으로 사용되지 않는다.
Parallel GC
- Young Generation에서는 병렬로 GC를 수행하여 Serial GC보다 높은 처리량을 제공한다.
- Old Generation에서도 병렬로 GC를 수행하는 Parallel Old Gc를 옵션으로 활성화 할 수 있다.
- Serial GC에 비해 개선되었으나 여전히 Major GC 시 STW 현상이 발생하며, 이로인해 응답 시간이 길어질 수 있다.
- 다중 코어 환경에서 높은 처리량을 요구하는 애플리케이션(예: 배치 처리)에 적합하다.
CMS(Concurrent Mark-Sweep) GC
- Old Generation Gc의 대부분 작업을 애플리케이션 스레드와 동시에 수행하여 STW 시간을 최소화 하는 것을 목표
- STW 시간을 줄이는 데 효과적이지만, 처리량이 Parallel GC보다 낮고, 메모리 단편화 문제가 발생할 수 있으며, Concurrent Mode Failure라는 상황이 발생할 수 있다.
- Java 9에서 deprecated 되었으며, 이후 버전에서는 G1 또는 ZGC/Shenandoah GC 사용을 권장하고 있다.
G1(Garbage-First) GC
- 높은 처리량과 짧은 응답 시간을 모두 목표로 하는 가비지 컬렉터
- 힙을 여러 개의 작은 영역으로 나누어 관리하며, 가장 효율적인 영역부터 가비지 대상 객체를 수징한다.
- 대규모 힙 환경에서 좋은 성능을 보인다.
- Mark and Sweep과 Copying Collection 방식을 혼합하여 사용한다.
- Java 9 이후 기본 가비지 컬렉터로 채택되었다.
ZGC(Z garbage Collector)
- 매우 낮은 Stop-the-World 시간을 목표로 하는 가비지 컬렉터
- 수십 테라바이트 크기의 힙에서도 10ms 미만의 Stop-the-World 시간을 유지하려고 한다.
- Load Barrier라는 기술을 사용하여 객체의 이동을 관리하며, Copying Collection 방식을 사용한다.
Shenandoah GC
- ZGC와 유사하게 매우 낮은 Stop-the-World 시간을 목표로 하는 가비지 컬렉터
- OpenJDK 프로젝트에서 개발되었으며, 다양한 플랫폼에서 사용 가능하다.
- Concurrent Mark-Sweep과 Copying Collection 방식을 혼합하여 사용하며, Brooks 포인터라는 기술을 활용
환경별 가비지 컬렉터 선택
다양한 환경 및 애플리케이션 특성에 따라 적합한 가비지 컬렉터 선택은 성능에 큰 영향을 미칠 수 있다.
- 낮은 지연 시간 요구
- G1 GC : 대부분의 경우 좋은 선택이며 짧은 STW 시간과 높은 처리량도 어느정도 만족
- ZGC : 매우 엄격한 낮은 지연 시간 요구사항이 있을 경우 고려 가능, Linux 64비트 환경에서 STW 시간을 10ms 미만으로 유지하려고 함
- Shenandoah GC : ZGD와 유사하게 매우 낮은 지연 시간을 목표로하나, 다양한 플랫폼에서 사용 가능 - 높은 처리량 요구
- Parallel GC : 멀티코어 환경에서 병렬로 가비지 컬렉션을 수행하여 높은 처리량을 제공하나, STW시간이 길어질 수 있다. - 메모리 사용량 제한적인 환경
- Serial GC : 단일 스레드로 동작하여 오버헤드가 적으나 STW가 상대적으로 길다. - 대규모 힙(Heap) 환경
- G1 GC : 큰 힙을 효율적으로 관리하며, STW 시간 제어 가능
- ZGC, Shenandoah GC : 매우 큰 힙에서도 낮은 지연 시간을 유지하는데 강점을 가짐
'Java' 카테고리의 다른 글
[Java] Record, Sealed Class를 활용한 객체 생성 및 관리 (0) | 2025.04.02 |
---|---|
[Java] Java 원격 디버깅(Java Remote Debugging) (0) | 2025.01.08 |
[Java] JVM의 한계와 GraalVM 살펴보기 (1) | 2024.12.16 |
[Java] JVM Warm up - if(kakao)2022 (1) | 2024.11.11 |
[Java] 회원 시스템 분산 트랜잭션(JTA) 처리와 성능 이슈 해결 (1) | 2024.10.31 |