업데이트 버전입니다.
메모리 누수를 방지하고 애플리케이션의 안정적인 실행을 위해, JVM이 힙 영역에서 객체의 생존 여부를 주기적으로 검사하여, 더 이상 사용되지 않는 객체를 자동으로 정리하는 기능

JVM에서 메모리 관리를 위해 사용되며 더 이상 참조되지 않는 객체들을 자동으로 탐지하고 해제하는 역할을 수행
이를 통해, 메모리 관리를 효율적으로 처리하며 프로그램 실행 중 메모리 누수를 방지하고 메모리 사용을 최적화합니다.
또한, 개발자들은 가비지 컬렉터를 통해 메모리 관리에 대한 직접적인 관여하지 않아도 됩니다.
가비지 컬렉터는 힙 내의 메모리에서 이를 관리
자바에서 참조란 객체 간의 연결 관계를 의미하며, 한 객체가 다른 객체를 참조하면 그 객체는 여전히 접근 가능한 상태로 간주됨
가비지 컬렉터는 이러한 참조 체인을 따라가며 살아 있는 객체를 식별하고, 어떤 객체도 참조하지 않는 객체를 가비지로 판단하여 메모리에서 회수함
메모리 영역 중에서 힙 영역 의 구조는 Young Generation과 Old Generation으로 구성되어 있습니다.

Young Genration : 새로 생성된 객체들이 할당되는 공간을 의미
Old Generation : 일정 시간이 지나거나 메모리가 부족할 때, 살아남은 객체들이 이동하는 공간을 의미
| 힙 영역 요소 | 상세 요소 | 설명 |
|---|---|---|
| Young Genration | Eden Area | 새로 생성된 객체들이 할당되는 공간을 의미, 일정 시간이 지나서 살아남은 객체들은 두 개의 Survivor 영역 중 하나로 이동 |
| Young Genration | Survivor Area | Eden 영역 객체들 중 일정 시간 동안 살아남은 객체들을 보관하는 공간 |
| Old Genration | Tenured Area | Young 영역에서 일정 시간이 지나거나 메모리가 부족할 때 살아남은 객체들이 이동하는 공간 |
메모리 영역에서 동작
Young Genration과 Old Genration의 메모리 영역 내의 가비지 컬렉터가 수행되는 작업들은 ‘Minor GC’와 ‘Major GC’에 의해 수행됨

| 분류 | Minor GC | Major GC ( = Full GC ) |
|---|---|---|
| 수행 영역 | Young Genration( Eden 영역, Survivor1, 2 영역 ) | Old Genration |
| 빈도 | 자주 발생 | 상대적으로 드묾 |
| 속도 | 빠르고 짧은 일시 정지 시간 | 느리고 긴 일시 정지 시간 |
| 정의 | Eden 영역과 Survivor 영역을 검사하여 사용하지 않는 객체를 제거하고, 남은 객체를 Survivor 영역으로 이동시킴 (해당 과정을 반복하여 Young Genration의 메모리를 관리 ) | Young Generation에서 살아남은 객체들이 이동되는 곳이며 Old Generation 전체를 검사하여 사용하지 않는 객체를 제거 |
| 목표 | 살아있는 객체를 식별하고 메모리를 해제하여 힙 영역을 최소화 | 전체 힙 영역을 정리하여 가비지를 제거하고 메모리를 최적화 |
copy & Scavenge 알고리즘을 사용하여 GC를 진행 JVM은 Eden, S0, S1 중 하나만 항상 비워두며, 살아남은 객체를 번갈아 복사함객체 생성 ( new ) → Eden에 저장
대부분의 새 객체는 Eden 영역에 생성되며, 이 공간이 가득 차면 Minor GC가 트리거됨
Minor GC 시작 ( Stop-the-World )
GC가 시작되면 모든 애플리케이션 스레드는 잠시 멈춤 ( STW )
마킹 ( Marking )
Eden과 Survivor 영역에서 참조되고 있는 객체( 살아 있는 객체 )를 식별하여 GC Root(스택, static 변수 등)에서 시작해 참조 체인을 따라가며 추적함
복사 (Copying)
GC 이후 살아 있는 객체만 비워져있는 S1 영역으로 복사하고, Eden 영역과 S2 영역은 비워지게 됩니다.
( 다음 GC에는 S2 영역으로 복사되고 Eden 영역과 S1 영역은 비워짐 … 계속 반복 )
Survivor 교체
이전의 S1이 새 S0가 되고, S0는 비워지고, 살아남은 객체는 몇 번의 GC를 거친 후 Old 영역으로 승격됨
**왜 Survivor은 두 개의 공간으로 이루어져 있나 ??**
Survivor 영역은 복사를 통해 살아 있는 객체만 유지하고, 죽은 객체는 복사하지 않고 버리는 방식을 사용
⇒ 복사하는 방식 때문에 한 Survivor는 항상 비워진 상태여야 함
⭐️⭐️
GC가 발생할 때마다 두 개의 Survivor 영역은 From 공간과 To 공간 역할을 번갈아 가며 수행합니다.
살아남은 객체는 항상 비어있는 To 공간으로 복사된 후, 다음 GC에는 From과 To 역할이 바뀝니다
이러한 GC 알고리즘을 Copy & Scavenge라고 합니다.
**승격의 시점은 ??**
객체마다 Age( 생존 횟수 )가 있음
일정 횟수(기본 15회, -XX:MaxTenuringThreshold로 조절)를 넘기면 → Old Generation으로 승격됨
객체를 그냥 삭제하지 않고 복사하는 이유 : 메모리 단편화를 방지하고, 살아 있는 객체를 한쪽으로 몰아넣어(압축) 남은 공간을 한 번에 비우기 위함
메모리 단편화를 방지하고, 불필요한 객체 제거가 효율적이며, 압축 효과가 커짐
종료 및 애플리케이션 재개
메모리 정리가 완료되면 STW가 해제되고, 애플리케이션 실행이 재개됩니다.
일반적으로 Stop-the-World 발생처리 범위가 크기 때문에 속도가 느리고 성능 영향이 큼Old 영역에 객체가 가득 찼을 때
Survivor 영역에서 승격된 객체가 Old 영역에 들어갈 공간이 없을 때
명시적으로 System.gc() 호출 시 ( 경우에 따라 Full GC 발생 )
밑에서 설명하는 가비지 컬렉터의 종류 방식에 따라 이루어짐
( 가장 전통적이고 기본적인 Major GC 방식은 Mark-Sweep-Compact 방식임 )
메모리 영역에서 동작 상세 과정

New Object Creation ( 새로운 객체 생성 )
새로운 객체가 생성되는 메모리 할당 단계에서는 JVM 런타임이 Young Generation 영역의 Eden 공간에 객체를 할당합니다.
Young Genration 내에서 객체 이동 ( Promotion Inside Young Genration )
객체 생성 이후 일정 시간이 지나거나 Eden 영역이 가득 차면 Minor GC가 발생합니다. 가비지 컬렉터는 Eden 영역과 현재 사용 중인 Survivor 영역에 있는 객체들을 스캔하여 참조되지 않은 객체들은 식별되어 메모리에서 해제되며 참조되어 살아남은 객체들은 비어있던 다른 Survivor 영역으로 이동합니다
Young Generation에서 Old Genration으로 승격 ( Promotion From Young to Old Gernation )
Survivor 영역에 있는 객체들 중 일정한 조건을 충족한 객체들을 Old Generation으로 이동시킴으로써 이루어집니다.
이를 통해 오랫동안 사용되는 객체들은 Old Generation에서 관리되며, Young Generation에서는 주로 단 기간만 사용되는 객체들이 관리됩니다.
STW( Stop the World )
JVM에서 가비지 컬렉션 작업 중에 발생하는 애플리케이션의 일시적인 중단을 의미합니다.
STW가 발생하면 애플리케이션의 모든 실행 스레드가 정지됩니다. 이는 가비지 컬렉터가 힙 메모리를 정리하고 객체의 수명 주기를 관리하기 위해 필요한 과정입니다.
일반적으로 매우 짧은 시간 동안 백그라운드에서 진행되는 작업이며, 애플리케이션의 성능에 큰 영향을 미치지 않지만, STW가 길게 지속되거나 너무 자주 발생할 경우 애플리케이션의 응답 시간이 느려질 수 있으므로, 개발자는 가비지 컬렉션을 최적화하고 STW 시간을 최소화 할 수 있도록 해야합니다.
가비지 컬렉터 : JVM 내에서 컬렉션을 진행하는 도구 또는 하위 시스템
직렬 가비지 컬렉터 ( Serial Garbage Collector )
단일 스레드에서 컬렉션 작업을 처리하고 작업을 순차적으로 진행하는 방식

최대한 메모리를 적게 쓰면서 어떻게든 GC를 수행해야 할 때, 제한적인 환경에서 사용하는 방식
단일 스레드에서 GC가 진행되므로 다른 GC 방식보다 처리 시간이 오래 걸립니다.
병렬 가비지 컬렉터 ( Parallel Garbage Collector, 기본적으로 CPU 코어 수에 비례 )
여러 스레드’에서 컬렉션 작업을 병렬로 작업을 처리하는 방식

여러 개의 GC 전용 스레드가 동시에 가비지 컬렉션 작업을 수행하는 방식의 GC
여러 개의 스레드를 활용해 동시에 가비지 컬렉션을 수행함으로써, 단일 스레드로 처리하는 Serial GC보다 빠르게 메모리를 회수할 수 있는 방식, Stop-the-World 방식이긴 하지만, 다중 스레드를 통해 GC 시간을 최소화하는 데에 중점을 둠
반대로, 병렬 스레드에서 처리가 되므로 CUP 자원을 더 많이 사용하게 될 수 있습니다.
동시 마크 스위프트 가비지 컬렉터 (Concurrent Mark Sweep Garbage Collector, CMS GC)
애플리케이션의 스레드 작업을 중단하지 않고 동시에 컬렉션 작업을 수행하는 방식
⇒ 대규모 메모리에서도 일시 중단 시간을 최소화할 수 있음

| 단계 | 설명 | STW 여부 |
|---|---|---|
| 1. Initial Mark | GC 루트에서 직접 참조되는 객체만 빠르게 표시 | 짧음 |
| 2. Concurrent Mark | 참조 체인을 따라가며 객체들을 백그라운드에서 마킹 | 동시 실행 |
| 3. Remark | 놓쳤을 수 있는 객체 다시 확인 ( 멀티스레딩 중 변한 참조 등 ) | 짧음 |
| 4. Concurrent Sweep | 수집 대상 객체를 동시적으로 제거 | 동시 실행 |
수행과정을 통해 일시 중단 시간을 최소화하면서 가비지 컬렉션 작업을 수행하기에 대규모 메모리에서도 애플리케이션의 응답성을 유지할 수 있지만, 병렬 가비지 컬렉터와 달리 애플리케이션 스레드와 병행하여 작업하기 때문에 일부 CPU 자원을 가비지 컬렉션에 사용하게 될 수 있음
[ 과정 ]
가비지 컬렉션 작업을 여러 단계로 분할
애플리케이션 스레드와 병행하여 객체의 수명 주기를 추적하고 가비지 객체를 마킹
이후, 애플리케이션 스레드를 중단시키고 가비지 객체를 스위핑 하여 메모리를 확보
중단된 애플리케이션 스레드를 다시 실행하여 가비지 컬렉션 작업을 완료함
마크 and 스위프트 알고리즘
메모리를 할당하는 과정에서 추가적인 정보를 유지하는 방식, 가비지 컬렉터는 메모리 할당 시 객체에 마크를 지정하고, 가비지 컬렉션 단계에서 마크되지 않은 객체들을 가비지로 판단하고 회수 하는 방식
참조 체인을 따라가며 객체들을 마크하고, 마크되지 않는 객체들을 가비지로 판단하여 회수하여 메모리를 확보하고 관리하는 방식
표시 단계 ( Mark )

이 단계에서는 모든 도달 가능한 객체를 식별하기 위해 루트 객체들을 찾아 탐색
루트 객체들은 주로 프로그램의 전역 변수, 스택 변수, 레지스터 등에 저장된 객체들, 이후 루트 객체들이 참조하는 모든 객체를 재귀적으로 탐색하며 마킹
정리 단계 ( Sweep )
마킹되지 않은 모든 객체들을 해제
⇒ 메모리 할당 영역을 스캔하면서 마킹되지 않은 객체들을 발견하면 이들 객체들의 메모리를 해제
즉, 더 이상 사용되지 않는 객체들이 메모리에서 제거됨
압축 단계 ( Compacting )

가비지 컬렉터는 메모리에서 제거된 객체들로 인해 생긴 빈 공간을 모아서 압축하여 메모리의 단편화를 최소화하고, 연속된 메모리 공간을 확보
Garbage-First (G1) 가비지 컬렉터 (Garbage-First Garbage Collector, G1 GC)
힙을 동일한 크기의 형태로 분할하여 우선순위를 지정한 다음 우선순위에 따라 청크에 대해 병렬 가비지 수집기를 수행하는 방식
청크
힙 영역을 구성하는 작은 블록을 의미, 이 청크들은 힙을 여러 개의 리전으로 분할하는 데 사용됨
각 청크는 고정된 크기를 가지며 가장 많은 가비지를 가진 리전부터 우선적으로 가비지 컬렉션의 대상으로 선택됨

가비지 컬렉션 작업을 일부 영역에서만 수행하고 나머지 영역에서는 계속 작업을 할 수 있도록 하여 일시 중단 시간을 최소화할 수 있으며, 가비지 컬렉션 작업을 병렬로 처리하므로 다른 애플리케이션 작업과 함께 실행되어 애플리케이션의 응답성을 유지할 수 있음
대규모 메모리를 가진 애플리케이션에서 주로 사용되며, 가비지 컬렉션 작업의 일시 중단 시간을 최소화하면서 응답성을 유지하는 것이 중요한 환경에서 효과적임
[ 과정 ]
객체를 복사하는 이유 : 메모리 단편화를 방지하고, 살아 있는 객체를 한쪽으로 몰아넣어(압축) 남은 공간을 한 번에 비우기 위함
메모리 단편화를 방지하고, 불필요한 객체 제거가 효율적이며, 압축 효과가 커짐
JVM 실행 시 전달되는 매개변수로, 자바 애플리케이션의 동작을 제어하고 구성하는데 사용됨

가비지 컬렉터 최적화 옵션

JVM이 알아서 가비지 컬렉션을 잘해주는데, 왜 굳이 GC 튜닝까지 해야 하느냐라고 한다면
⇒ 실시간 응답성 확보, 메모리 최적화, 중단 시간 최소화 같은 요구사항이 있는 시스템에서는 튜닝을 통해 성능을 안정적으로 유지
튜닝 목표 설정
JVM 튜닝의 출발점은 목표 설정임, 어떤 목적이 핵심인지 먼저 명확히 정해야 함
| 목표 예시 | 설명 |
|---|---|
| 메모리 사용 최소화 | 힙 사이즈 절감, GC 비용 줄이기 |
| GC 횟수 최소화 | 객체 생존 기간 늘리기, 승격 조절 |
| GC 시간 단축 | GC pause 시간 ↓, 응답성 향상 |
| Throughput ↑ | 전체 처리량 ↑ ( Parallel GC 적합 ) |
| Response Time ↑ | 짧은 응답 시간 ( CMS/G1/ZGC 적합 ) |
2. 힙 및 메타영역(Perm/Metaspace) 크기 설정
3. GC 로그 수집 및 성능 테스트
4. GC 동작 패턴 분석 및 영역 비율 조정
5. GC 알고리즘 선택 - 목표에 따라 적절한 GC를 선택
| 목표 | 추천 GC |
|---|---|
| Throughput ↑ | -XX:+UseParallelGC (병렬 GC) |
| 응답 시간 ↓ | -XX:+UseConcMarkSweepGC (CMS, Java 9 미만) |
| 응답 시간 + 낮은 pause | -XX:+UseG1GC (기본값, Java 9 이상) |
| 초저지연 (ms 단위 pause) | ZGC, Shenandoah (최신 JVM) |
6. 반복 테스트 및 파라미터 튜닝
튜닝은 한 번으로 끝나지 않음
주요 JVM 파라미터
| 파라미터 | 설명 |
|---|---|
| -Xms, -Xmx | 힙 크기 |
| -Xmn | Young 영역 크기 |
| -XX:NewRatio | Old:New 비율 |
| -XX:SurvivorRatio | Eden:Survivor 비율 |
| -XX:MaxTenuringThreshold | Old 영역 승격 기준 횟수 |
| -XX:MaxMetaspaceSize | 메타영역 크기 (Java 8 이상) |
로그 분석 → 조정 → 테스트 반복