JVM 의 Runtime Data Area 중 Heap 영역에 대해서 알아봅니다.
Heap 영역
- JVM 에서 new 연산자를 통해 생성되는 모든 객체와 배열이 저장되는 공유 메모리 영역
- 모든 스레드가 이 영역에 접근 할 수 있으므로, 동시성이 중요한 부분이기도 함
- 목적
- 객체 / 배열 / 객체 헤더 정보 등이 저장됨
- 프로그램 실행 중에 필요 한 만큼 객체를 생성하고, 그 수명이 끝난 객체들을 회수하여 메모리 사용을 최적화
- JVM 옵션
- -Xms / -Xmx 옵션을 통해, 힙의 초기 크기와 최대 크기를 지정 할 수 있음
- 어플리케이션의 메모리 사용 패턴에 맞춰 조정하며, GC 성능 및 어플리케이션의 전체 성능에 큰 영향을 미침
- 동시성
- 힙은 여러 스레드가 공유하는 영역이기 때문에, 동시성 문제가 발생 할 수 있음
- 이를 해결하기 위해, JVM은 다양한 동기화 기법 및 GC 알고리즘을 활용 하여, 동시 접근과 메모리 일관성 문제를 해결
- 메모리 최적화
- 객체의 재사용, 객체 풀링, interned 문자열 같은 최적화 기법을 통해 힙의 효율성을 극대화
- GC 로그 분석이나, Heap Dump 등을 통해 어플리케이션의 메모리 사용 상태를 모니터링 하고 튜닝 할 수 있음
- 성능 / 안정성
- 힙 영역의 크기와 GC 알고리즘의 선택은, JVM 성능과 어플리케이션 응답 속도에 직접적인 영향을 미침
- 올바른 힙 튜닝은 OOM 같은 문제를 예방하고 시스템 안정성성을 높일 수 있음
Heap memory 구조
- Young Generation
- 방금 생성된 객체가 먼저 놓이는 곳
- Eden 영역
- 객체가 생성된 직후엔, 기본적으로 이 영역에 할당 됨
- Eden 에서 대부분의 객체는 사용 후 GC에 의해 제거 됨
- Survivor 영역
- Eden 영역에서 사용 되고 남은 객체들은 두 개의 작은 공간 ( S0, S1 ), 즉 Survivor 영역으로 이동 됨
- 객체는 한 Survivor 영역에서 다른 Survivor 영역으로 복사 되면서, 반복적으로 살아남을 경우 나중에 Old Generation 으로 이동 됨
- Old Generation ( Tenured Generation )
- 젊은 세대를 여러 번 거쳐 살아남은 객체들이 저장 됨
- Young generation 보다 GC 주기가 길고, 한번에 많은 객체를 처리하지 않음
- GC시, 객체 이동 및 복사 비용이 더 많이 드는 경우가 있기 때문에, GC 알고리즘에 따라 압축 / 복잡한 알고리즘이 활용 됨
Garbage collection
- Young generation GC ( Minor GC )
- Copying Collection 방식으로 동작
- Eden 영역에 할당된 대부분의 객체는, 생성 후 사용되지 않으면 Minor GC 에 의해 제거
- 살아남은 객체는 Eden 에서, Survivor 영역 중 하나로 복사
- Survivor 영역 간에는 교대로 복사 하면서, 살아남은 객체들을 옮김
- 여러 GC 사이클을 통과한 객체는 Old Generation 으로 승격
- 특징
- 대부분의 객체가 빠르게 사라지기 때문에, 복사 알고리즘이 빠르고 단순하며, 파편화도 줄일 수 있음
- Copying Collection 방식으로 동작
- Old generation GC ( Major GC / Full GC )
- Mark-Sweep
- Mark → 힙 내 모든 객체를 탐색하여, 도달 가능한 객체와 도달 불가능한 객체를 표시
- Sweep → 도달 불가능한 객체들을 메모리에서 해체
- Mark & Sweep 단계는, 도달 불가능한 객체들을 메모리에서 해제 한 뒤, 재정리 작업이 없음
- 따라서, 메모리 조각화 ( 단편화 ) 문제가 생길 수 있음
- Mark-Compact
- Mark 후에, 살아있는 객체들을 한쪽으로 밀어 모으고, 남은 빈 공간을 하나로 합침
- 조각화 문제가 줄어들지만, 객체를 이동하는 복사 비용이 추가 됨
- G1 GC ( Garbage First GC )
- 영역 기반 ( Region-based ) GC로, 힙을 작은 영역 ( Region ) 으로 나누어 처리
- 각 영역의 GC 우선 순위를 정해, 가장 많은 쓰레기가 있는 영역부터 청소하는 방식으로 동작
- G1 GC는 단편화 문제를 해결하고, 예측 가능한 짧은 GC 정지를 목표로 함
- 정지 시간 목표 ( Pause-Time Goal )을 지정 할 수 있어, 예측 가능한 정지 시간을 제공
- 많은 JVM의 기본 GC로 채택되어 있음
- Young / Old Generation 경계를 넘어 전체 힙을 효율적으로 관리 할 수 있음
- 대규모 힙 환경에서 특히 유리하며, Full GC가 아닌 병렬적 / 지역적 GC를 통해 응답 지연이 줄어 듬
- Full GC 진행 될 땐, 자바 어플리케이션이 멈출 수 있는 이슈가 있음 ( stopping-the-world )
- Mark-Sweep
- 다른 GC 알고리즘들
- Serail GC
- 단일 스레드로 GC 작업을 수행하는 단순한 GC 알고리즘
- 작은 어플리케이션, 단일 CPU 환경에서 주로 활용
- 작은 힙 환경 / 개발 및 테스트 단계에서 많이 활용 되고, 멀티 코어 환경에서 병렬 처리 능력이 부족해 전체 어플리케이션 처리량이 낮음
- Parallel GC ( Throughput GC )
- 여러 스레드를 활용하여 GC 작업을 병렬로 수행
- Young Generation의 Minor GC 작업에 많이 사용되며, Full GC도 병렬로 수행 가능한 경우가 많음
- 서버 어플리케이션 등, 많은 CPU 코어를 가진 시스템에서 높은 처리량을 목표로 하는 환경에서 적합
- 병렬로 GC가 수행되어, 전체 GC 시간이 단축되고, 처리량이 향상 됨
- 멀티 스레드 GC의 경우 정지 시간이 길어 질 수 있으나, 높은 처리량을 우선시 하는 환경에서 채택
- Concurrent Mark-Sweep
- 대부분의 GC 작업을 어플리케이션 스레드와 동시에 진행하여, 정지 시간을 줄이는데 초점을 맞춤
- Pause time 을 최소화 해야 하는 대화형 어플리케이션이나, 실시간 시스템에 적합
- 메모리 단편화가 발생 할 수 있으며, 추가적인 동시 실행 오버헤드가 있을 수 있음
- Serail GC
"Android" 카테고리의 최근 포스팅
카테고리 모든 글 보기Kotlin - 코루틴 동작 원리 ( Continuation / CPS / State Machine ) | 2025. 04. 23 |
---|---|
JVM - Runtime Data Area - Thread | 2025. 04. 21 |
JVM - Runtime Data Area - Heap | 2025. 04. 21 |
JVM - Runtime Data Area - Method | 2025. 04. 19 |
JVM - Interned string | 2025. 04. 18 |
Android - 직렬화 | 2025. 04. 17 |
Hilt - ComponentScope | 2025. 04. 16 |
Kotlin - Channel | 2025. 04. 15 |
Android - ViewModel 에 대해서 | 2025. 04. 14 |
Android - Bundle 이란 | 2025. 04. 13 |