용어 정리
Garbage Collector (이하 GC)
C언어는 유효하지 않은 메모리인 가비지를 개발자가 직접 해제해 준다고 합니다.
Java는 개발자가 가비지를 직접 해제해 주는 일이 없습니다. JVM의 가비지 컬렉터가 불필요한 메모리를 알아서 정리해 주기 때문입니다.
가비지 컬렉터는 주기적으로 JVM의 heap 메모리를 점검하여 스택에서 참조되지 않는 객체를 메모리에서 해제하는 장치입니다.
Stop The World (이하 STW)
가비지 컬렉션을 실행하기 위해 JVM이 애플리케이션의 실행을 멈추는 작업입니다. GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, GC가 완료되면 작업이 재개됩니다.
모든 GC는 STW를 발생시키는데 Minor GC는 객체의 수명이 짧고 객체를 검사하지 않기 때문에 매우 빨라 애플리케이션에 거의 영향을 주지 않습니다. 반면에 Major GC의 경우 살아있는 모든 객체를 검사해야 하기 때문에 오랜 시간이 걸립니다. GC의 성능 개선을 위해 튜닝을 한다고 하면 보통 STW의 시간을 줄이는 작업을 하는 것입니다.
Mark & Sweep & Compact
Mark: 접근 가능한 객체에 Mark 하여 표시
Sweep: Mark되지 않은 객체들을 제거하는 과정
Compact: Sweep 과정에 의해 삭제되면 메모리 단편화가 발생하므로 빈자리를 채워주는 과정
GC의 종류
Serial GC
하나의 쓰레드로 GC를 실행하는 방식입니다.
하나의 쓰레드만 사용하다 보니 Stop The World 시간이 오래 걸립니다.
싱글 쓰레드 환경 및 Heap 영역이 매우 작을 때 사용하기 위한 방식입니다.
Pararell GC
여러 개의 쓰레드로 GC를 실행하는 방식입니다.
여러 개의 쓰레드를 사용하므로 Stop The World 시간이 짧아지고, 멀티 코어 환경에서 애플리케이션 처리 속도를 향상하기 위해 사용됩니다.
GC를 위한 쓰레드 수, 일시 정지 시간, 처리량, heap size 등을 정할 수 있습니다.
java 7~8 버전의 default GC 방식입니다.
CMS GC
Concurrent-Mark-Sweep 의 줄임말로 Stop The World 시간을 최소화하기 위해 고안되었습니다.
접근할 수 없는 객체를 한 번에 찾지 않고 나눠서 찾는 방식을 사용합니다. (4 STEP)
메모리와 CPU를 많이 사용하고, Mark And Sweep 과정 이후 메모리 파편화를 해결하는 Compaction 과정이 기본적으로 제공되지 않기 때문에 G1 GC가 등장하면서 대체되었다고 합니다.
Initial Mark: GC Root가 참조하는 객체만 마킹 (STW 발생)
Concurrent Mark: 참조하는 객체를 따라가며, 지속적으로 마킹
Remark: Concurrent Mark 과정에서 변경된 사항이 없는지 다시 한번 마킹하며 확정하는 과정 (STW 발생)
Concurrent Sweep: 접근할 수 없는 객체를 제거하는 과정
G1 GC
G1은 Garbage First의 줄임말입니다. 이전 GC와 비교했을 때, 고정된 메모리 크기로 각 Generation을 구분했던 것과 달리 힙 영역을 동일한 크기의 Region으로 나눠 관리합니다.
런타임에 G1 GC가 필요에 따라 영역별 Region 개수를 튜닝합니다. 이에 따라 Stop The World를 최소화할 수 있게 되어 java9 이상부터 default GC로 사용합니다.
-XX:G1HeapRegionSize: JVM 힙은 2048개의 region으로 나뉠 수 있으며, 해당 옵션을 통해 1MB ~ 32MB 사이로 지정될 수 있습니다.
G1 GC는 일시 정지 시간을 줄이기 위해 각 스레드가 자신만의 region을 잡고 작업하는 방식으로 병렬 GC를 수행합니다.
신규로 정의된 영역
Humongous: Region 크기의 50%를 초과하는 큰 객체를 저장하기 위한 공간입니다. 이 Region에서는 GC가 최적으로 동작하지 않습니다.
Available/Unused: 아직 사용되지 않은 Region을 의미합니다.
동작과정
1. Minor GC
Young 영역에서는 용량이 일정 수준으로 올라가면 Minor GC가 발생하면서 Survivor 영역으로 객체들이 복사되고 age-bit 값이 증가합니다.
2. Promotion
age-bit 가 일정 값 이상으로 올라가면 old 영역으로 객체를 넘겨줍니다.
java8 Parallel GC 기준 age-bit 15가 되면 promotion이 진행됩니다.
3. Major GC
Old 영역이 꽉 차면 Major GC 가 발생합니다.
여기까지는 다른 GC도 동일하게 동작하는 과정입니다.
4. Full GC
Young, Old 영역 모두 꽉 찼을 경우 발생하는 GC입니다.
4.1 Initial Mark
STW가 발생합니다. Survivor 영역에서 Old 영역을 참조하고 있는 영역들을 찾아서 마킹합니다.
4.2 Root Region Scan
Initial Mark 단계에서 찾은 Surivor 영역에 대한 GC 대상 객체 스캔 작업을 진행합니다.
4.3 Concurrent Mark
전체 힙 영역에 대한 스캔으로 살아있는 객체가 존재하는 Region만 식별합니다.
4.4 Remark
STW가 발생하며 최종적으로 살아남은 객체를 식별합니다.
4.5 Cleanup
STW가 발생하며 살아남은 객체가 가장 적은 Region의 GC대상을 제거합니다. 이후 STW를 끝내고, 앞선 GC 과정에서 완전히 비워진 영역을 Freelist에 추가하여 재사용될 수 있게 합니다.
4.6 Copy
GC대상이었지만 Cleanup 과정에서 완전히 비워지지 않은 지역의 남은 객체를 Avaliable Region으로 복사하여 Compaction 작업을 수행합니다.
참고 자료
'Java' 카테고리의 다른 글
Java 함수형 인터페이스 (0) | 2024.12.17 |
---|---|
Java static Map 초기화 한번만 하기 (1) | 2023.12.15 |
소나 큐브 사용법(Sonar Qube) (0) | 2023.11.29 |
Lombok (1) | 2023.11.28 |
Java Optional (0) | 2023.09.29 |