반응형
해당 글에서는 JVM에서 가비지 컬렉터에 대해 이해하고 종류들을 이해하며 동작과정에 대해 이해를 돕기 위해 작성한 글입니다.
💡 [참고] JVM에 동작과정, 메모리 영역(Runtime Data Area)에 대해 관심이 있으시면 아래의 글이 큰 도움이 됩니다.
1) 가비지 컬렉터(GC, Garbage Collector)
💡 가비지 컬렉터(GC, Garbage Collector)
- JVM에서 메모리 관리를 위해 사용이 되며 ‘더 이상 참조되지 않는 객체들을 자동으로 탐지하고 해제’하는 역할을 수행합니다. 이를 통해 메모리 관리를 효율적으로 처리하며 프로그램 실행 중에 메모리 누수를 방지하고 메모리 사용을 최적화합니다.
- 또한 개발자들은 가비지 컬렉터를 통해 메모리 관리에 대한 직접적인 관여 없이도 안정적인 프로그램을 작성할 수 있습니다.
- 가비지 컬렉터는 메모리 영역(Runtime Data Area)에서 중에서 ‘힙 영역(Heap Area)’내에서 이를 관리하고 사용합니다.
[더 알아보기]
💡 가비지 컬렉터에서 참조를 한다는 말은 무슨 의미일까?
- 참조는 프로그램에서 객체 객체 간의 연결을 나타내는 것을 말합니다. 객체가 다른 객체를 참조하면 참조되는 객체는 참조 체인을 통해 계속해서 접근 가능한 상태가 됩니다.
- 가비지 컬렉터는 참조되지 않은 객체를 식별하기 위해 참조 체인을 따라가며 객체들을 스캔합니다. 참조되지 않은 객체는 가비지로 간주되고 회수됩니다.
2) 메모리 영역 내의 가비지 컬렉터
💡 힙 영역(Heap Area) 안에 존재하는 가비지 컬렉터에 대해 어떠한 동작으로 수행을 하는지 확인해 봅니다.
1. 메모리 영역
💡 메모리 영역(Runtime Data Area) 중에서 ‘힙 영역(Heap Area)’ 의 구조는 Young Generation과 Old Generation으로 구성되어 있습니다.
힙 영역 | 요소 상세 | 요소 설명 |
Young Genration | Eden Area | - ‘새로 생성된 객체들’이 ‘할당’되는 공간을 의미합니다 - 일정 시간이 지나서 살아남은 객체들은 두 개의 Survivor 영역 중 하나로 이동합니다. |
Young Genration | Survivor Area | - Eden 영역 객체들 중 ‘일정 시간 동안 살아남은 객체들’을 ‘보관’하는 공간을 의미합니다. |
Old Genration | Tenured Area | - Young 영역에서 ‘일정 시간이 지나거나 메모리가 부족할 때 살아남은 객체’들이 ‘이동’하는 공간입니다. |
2. 메모리 영역에서 동작
💡 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 전체를 검사하여 사용하지 않는 객체를 제거합니다. |
속도 | 빠르고 짧은 일시 정지 시간 | 느리고 긴 일시 정지 시간 |
목표 | ‘살아있는 객체를 식별’하고 메모리를 해제하여 힙 영역을 최소화 | ‘전체’ 힙 영역을 정리하여 가비지를 제거하고 메모리를 최적화 |
3. 메모리 영역에서 동작 상세 과정
💡 메모리 영역에서 동작 상세 과정
1. 새로운 객체 생성 : New Object Creation
- 메모리 할당 과정에서 새로운 객체를 생성하는 단계입니다. 이 단계에서는 Young Generation 영역에서 새로운 객체가 생성이 되며 이후 가비지 컬렉터는 ‘Eden 영역’에 해당 객체를 할당합니다.
2. Young Genration 내에서 객체 이동: Promotion Inside Young Genration
- 객체 생성 이후 일정 시간이 지나거나 Eden 영역이 가득 차면 가비지 컬렉터는 Eden 영역에 있는 객체들을 스캔하여 참조되지 않은 객체들을 식별하고 메모리에서 해제합니다. 이때 참조되지 않은 객체들은 가비지로 간주되어 회수되며 참조되어 살아남은 객체들은 Survivor 영역으로 이동됩니다.
3. Young Generation에서 Old Genration으로 승격 : Promotion From Young to Old Gernation
- Survivor 영역에 있는 객체들 중 일정한 조건을 충족한 객체들을 Old Generation으로 이동시킴으로써 이루어집니다. 이를 통해 오랫동안 사용되는 객체들은 Old Generation에서 관리되며, Young Generation에서는 주로 단기간만 사용되는 객체들이 관리됩니다.
4. STW(Stop the World)
💡 STW(Stop the World)
- JVM에서 발생하는 가비지 컬렉션 작업 중에 일어나는 ‘일시적인 중단’을 의미합니다. 이는 애플리케이션의 모든 스레드를 정지시키는 것을 의미하며 가비지 컬렉션 작업을 위해 힙 메모리를 정리하고 객체의 수명 주기를 관리합니다.
- 메모리 누수와 같은 문제를 예방하고 JVM의 성능을 최적화하기 위해 필요한 작업입니다.
(* 추후 가비지 컬렉터의 튜닝 부분에 중요한 작업입니다.)
- 일반적으로 백그라운드에서 진행되는 작업이며 애플리케이션의 성능에 큰 영향을 미치지 않습니다 그러나 STW가 길게 지속되거나 너무 자주 발생할 경우 애플리케이션의 응답 시간이 느려질 수 있습니다. 따라서 개발자는 가비지 컬렉션을 최적화하고 STW 시간을 최소화하기 위해 다양한 방법을 고려해야 합니다.
3) 가비지 컬렉터의 종류
0. 요약
GC 종류 | 설명 | 장점 | 단점 | JVM 인자 |
Serial GC | 단일 스레드에서 컬렉션 작업을 순차적으로 진행하는 방식 | 작은 힙 크기에서 성능이 우수함 | 대규모 애플리케이션에서는 성능 문제 발생 가능성 | -XX:+UseSerialGC |
Parallel GC | 다중 스레드에서 컬렉션 작업을 병렬로 진행하는 방식 | 대규모 애플리케이션에서 높은 처리량 제공 | 일시 정지 시간이 길어질 수 있음 | -XX:+UseParallelGC |
CMS GC | 애플리케이션의 스레드 작업을 중단하지 않고 동시에 컬렉션 작업을 수행하는 방식 | 일시 정지 시간을 최소화하며 동시에 메모리를 수집하는 방식 | 처리량과 메모리 사용량에 제약이 있을 수 있음 | -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads= |
G1 GC | 힙을 동일한 크기의 형태로 분할하여 우선 순위를 지정한 다음 우선순위에 따라 청크에 대해 병렬 가비지 수집기를 수행하는 방식 | 대규모 힙에서 일시 정지 시간을 극적으로 줄일 수 있음 | GC 작업을 영역 단위로 실행하기 때문에 일시 정지 시간이 약간 발생 가능 | -XX:+UseG1GC |
1. 직렬 가비지 컬렉터 (Serial Garbage Collector)
💡 직렬 가비지 컬렉터 (Serial Garbage Collector)
- ‘단일 스레드’에서 컬렉션 작업을 처리하고 작업을 ‘순차적으로 진행’하는 방식을 의미합니다. 해당 과정을 통해 객체의 수명 주기를 추적하고 사용되지 않는 객체를 삭제하여 메모리를 확보합니다.
- 단일 스레드에서 작업 처리가 수행되기에 다른 가비지 컬렉션 방식보다 처리 시간이 오래 걸립니다.
- 반대로 단일 스레드에서 처리되므로 컬렉션 작업이 다른 애플리케이션 작업과 충돌하지 않는다는 장점이 있습니다.
2. 병렬 가비지 컬렉터 (Parallel Garbage Collector)
💡 병렬 가비지 컬렉터 (Parallel Garbage Collector)
- ‘여러 스레드’에서 컬렉션 작업을 ‘병렬로 작업을 처리’하는 방식을 의미합니다. 해당 과정을 통해 객체의 수명을 추적하고 사용되지 않는 객체를 삭제하여 메모리를 확보합니다
- 병렬 스레드에서 작업을 처리하기에 동시에 여러 작업을 수행하므로 처리 시간이 단일 스레드 방식에 비해 줄어들 수 있으며 다른 애플리케이션 작업과 함께 실행되기도 하며, 대규모 메모리에서 가비지 컬렉션을 수행할 때 성능을 향상될 수 있습니다.
- 반대로 병렬 스레드에서 처리가 되므로 CUP 자원을 더 많이 사용하게 될 수 있습니다.
3. 동시 마크 스위프트 가비지 컬렉터 (Concurrent Mark Sweep Garbage Collector, CMS GC)
💡 동시 마크 스위프트 가비지 컬렉터 (Concurrent Mark Sweep Garbage Collector, CMS GC)
- 가비지 컬렉션 작업을 애플리케이션의 스레드 작업을 중단하지 않고 동시에 컬렉션 작업을 수행하는 방식을 의미합니다. 이 방식은 대규모 메모리에서도 일시 중단 시간을 최소화할 수 있는 장점이 있습니다.
- 수행과정을 통해 일시 중단 시간을 최소화하면서 가비지 컬렉션 작업을 수행하기에 대규모 메모리에서도 애플리케이션의 응답성을 유지할 수 있습니다.
- 그러나 병렬 가비지 컬렉터와 달리 애플리케이션 스레드와 병행하여 작업하기 때문에 일부 CPU 자원을 가비지 컬렉션에 사용하게 될 수 있습니다.
💡동시 마크 스위프트 가비지 컬렉터 (Concurrent Mark Sweep Garbage Collector, CMS GC) 수행과정
1. 가비지 컬렉션 작업을 여러 단계로 분할하여 수행합니다
2. 애플리케이션 스레드와 병행하여 객체의 수명 주기를 추적하고 가비지 객체를 마킹합니다.
3. 이후, 애플리케이션 스레드를 중단시키고 가비지 객체를 스위핑 하여 메모리를 확보합니다.
4. 중단된 애플리케이션 스레드를 다시 실행하여 가비지 컬렉션 작업을 완료합니다.
3.1. 마크-앤-스위프트(Mark And Sweep) 알고리즘
💡 마크-앤-스위프트(Mark And Sweep)
- 메모리를 할당하는 과정에서 추가적인 정보를 유지하는 방식입니다. 가비지 컬렉터는 메모리 할당 시 객체에 마크(Mark)를 지정하고, 가비지 컬렉션 단계에서 마크되지 않은 객체들을 가비지로 판단하고 회수(Sweep) 하는 방식을 의미합니다.
💡 마크-앤-스위프트(Mark And Sweep) 동작 과정
1. 표시(Mark) 단계
- 이 단계에서는 모든 도달 가능한 객체를 식별하기 위해 루트(root) 객체들을 찾아 탐색합니다.
- 루트 객체들은 주로 프로그램의 전역 변수, 스택 변수, 레지스터 등에 저장된 객체들입니다. 이후, 루트 객체들이 참조하는 모든 객체를 재귀적으로 탐색하며 마킹(mark)합니다.
2. 정리(Sweep) 단계
- 이 단계에서는 마킹되지 않은 모든 객체들을 해제합니다.
- 메모리 할당 영역을 스캔하면서 마킹되지 않은 객체들을 발견하면 이들 객체들의 메모리를 해제합니다. 이로써 더 이상 사용되지 않는 객체들이 메모리에서 제거됩니다.
3. 압축(Compacting) 단계
- 가비지 컬렉터는 메모리에서 제거된 객체들로 인해 생긴 빈 공간을 모아서 압축합니다. 이렇게 함으로써 메모리의 단편화를 최소화하고, 연속된 메모리 공간을 확보합니다.
💡 결론적으로, 참조 체인을 따라가며 도달 가능한 객체들을 마크하고, 마크되지 않은 객체들을 가비지로 판단하여 회수하는 방식으로 메모리를 관리합니다.
4. Garbage-First (G1) 가비지 컬렉터 (Garbage-First Garbage Collector, G1 GC)
💡 Garbage-First (G1) 가비지 컬렉터 (Garbage-First Garbage Collector, G1 GC)
- 힙을 동일한 크기의 형태로 분할하여 우선순위를 지정한 다음 우선순위에 따라 청크에 대해 병렬 가비지 수집기를 수행하는 방식을 의미합니다.
- 가비지 컬렉션 작업을 일부 영역에서만 수행하고 나머지 영역에서는 계속 작업을 할 수 있도록 하여 일시 중단 시간을 최소화할 수 있습니다. 또한, 가비지 컬렉션 작업을 병렬로 처리하므로 다른 애플리케이션 작업과 함께 실행되어 애플리케이션의 응답성을 유지할 수 있습니다.
- 대규모 메모리를 가진 애플리케이션에서 주로 사용되며, 가비지 컬렉션 작업의 일시 중단 시간을 최소화하면서 응답성을 유지하는 것이 중요한 환경에서 효과적입니다.
💡 Garbage-First (G1) 가비지 컬렉터 (G1 가비지 컬렉터, G1 GC) 수행과정
1. Eden 영역과 Survivor 영역에서 가비지 객체를 마킹합니다.
2. 마킹된 객체를 특정 영역으로 복사하면서 메모리를 정리합니다.
3. 이 과정을 반복하여 가비지 컬렉션을 수행하고 최종적으로 Old 영역에서 가비지 컬렉션을 수행합니다.
[더 알아보기]
💡 가비지 컬렉터에서 청크(chunk)
- 힙 영역을 구성하는 작은 블록을 의미합니다. 이 청크들은 힙을 여러 개의 리전으로 분할하는 데 사용됩니다.
- 각 청크는 고정된 크기를 가지며 가장 많은 가비지를 가진 리전부터 우선적으로 가비지 컬렉션의 대상으로 선택합니다.
4) 가비지 컬렉터 JVM 옵션
1. JVM 인자(JVM Arguments)
💡 JVM 인자(JVM Arguments)
- JVM 실행 시에 전달되는 매개변수로, 자바 애플리케이션의 동작을 제어하고 구성하는 데 사용됩니다.
Option | 설명 |
-XX:+UseSerialGC | 직렬 가비지 컬렉터 사용 |
-XX:+UseParallelGC | 병렬 가비지 컬렉터 사용 |
-XX:+UseConcMarkSweepGC | CMS 가비지 컬렉터 사용 |
-XX:ParallelCMSThreads= | CMS 가비지 컬렉터 사용 - 사용할 스레드의 수 |
-XX:+UseG1GC | G1 가비지 컬렉터 사용 |
-XX:InitiatingHeapOccupancyPercent=<n> | G1 GC 수행을 시작하기 위한 힙 점유율 백분율을 설정합니다. 기본 점유율은 45 값을 가집니다 |
-XX:G1MixedGCLiveThresholdPercent=<t> | G1 GC 혼합(G1 Mixed) GC를 시작하기 위한 살아 있는 객체 비율 백분율을 설정합니다. t는 밀리초 단위의 시간을 의미하며 기본값은 65 값을 가집니다 |
-XX:G1HeapWastePercent=<r> | G1 GC에서 허용되는 힙 낭비 비율 백분율을 설정합니다.r은 region의 수를 의미하며 기본 값은 10입니다 |
2. 가비지 컬렉터 최적화 옵션
옵션 | 설명 |
-Xms<size> | 초기 힙 크기를 지정합니다. |
-Xmx<size> | 힙 크기를 최대화합니다. |
-Xmn<size> | Young Generation의 크기를 지정하는 데 사용됩니다. |
-XX:PermSize | 초기 영구 생성 크기 |
-XX:MaxPermSize | 영구 생성(PermGen)의 최대 크기를 지정하는 데 사용됩니다. |
99) 참고한 사이트
💡 추후 글에서는 JVM의 가비지 컬렉터를 실제 튜닝 해보는 방법에 대해서 확인해 봅니다!
오늘도 감사합니다. 😀
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] 접근 제한자/제어자(Access Modifier) 이해하기 : public, private, protected, default (0) | 2023.12.24 |
---|---|
[Java] API 캐시와 세션 이해하기 (1) | 2023.10.22 |
[Java] JVM(Java Virtual Machine) 이해하기 -2 : 메모리 영역(Runtime Data Area) (0) | 2023.10.07 |
[Java] JVM(Java Virtual Machine) 이해하기 -1 : 동작 과정 (0) | 2023.10.06 |
[Java] 반복문의 제어문(Control Flow Statement) 이해하기 (0) | 2023.10.03 |