JVM (Java Virtual Machine)
- 자바 가상 머신
- 자바와 운영체제 사이에서 중개자 역할을 수행하며, 자바가 운영체제에 구애 받지 않고 프로그램을 실행할 수 있도록 도와줌
- 가비지 컬렉터를 사용한 자동적인 메모리 관리, 스택 기반으로 동작
JVM 동작 방식
- 자바로 개발된 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일
- Class Loader를 통해 JVM Runtime Data Area로 로딩
- Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어짐
JVM 메모리 구조
Garbage Collector, Execution Engine, Class Loader, Runtime Data Area로, 4가지로 나눌 수 있음
(1) 클래스 로더 (Class Loader)
- JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈
- 런타임 시에 동적으로 클래스를 로드
(2) 실행 엔진 (Execution Engine)
- 클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명렁어 단위로 읽어서 실행
(3) 가비지 컬렉터 (Garbage Collector)
- GC는 힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할
(4) 런타임 데이터 영역 (Runtime Data Area)
- JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역
- 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있음
모든 스레드가 공유해서 사용 (GC의 대상)
- 힙 영역 (Heap Area)
- 메서드 영역(Method Area)
스레드(Thread) 마다 하나씩 생성
- 스택 영역(Stack Area)
- PC 레지스터 (PC Register)
- 네이티브 메서드 스택(Native Method Stack)
메서드 영역 (Method Area)
- 클래스, 인터페이스, 메소드, 필드, Static 변수 등이 생성되는 영역
힙 영역 (Heap Area)
- new 키워드로 생성된 객체와 배열이 생성되는 영역
- 주기적으로 GC가 제거하는 영역
스택 영역 (Stack Area)
- 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역
- 메서드 수행이 끝나면 프레임별로 삭제
PC 레지스터 (PC Register)
- Thread가 생성될 때마다 생성되는 영역
- 프로그램 카운터, 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역
네이티브 메서드 스택 (Native Method Stack)
- 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역 (보통 C/C++ 등의 코드를 수행하기 위한 스택)
Garbage Collection(GC)
- 자바의 메모리 관리 방법 중 하나
- JVM의 Heap 영역에서 동적으로 할당했던 메모리 중 필요없게 된 메모리 객체(garbage)를 모아 주기적으로 제거하는 프로세스
- 대상 - Unreachable: 객체가 참조되고 있지 않은 상태 (GC의 대상)
- 메모리가 언제 해제되는지 정확하게 알 수 없어 제어하기 힘들며, 가비지 컬렉션(GC)이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생되는 문제점 → Stop The World
Stop The World (STW)
- GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상
- GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어 서비스 이용에 차질이 생길 수 있음
Garbage Collection 청소 방식
- Mark 과정: 먼저 Root Space로부터 그래프 순회를 토앻 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾아서 마킹
- Sweep 과정: 참조하고 있지 않은 객체, 즉 Unreachable 객체들을 Heap에서 제거
- Compact 과정: Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축
JVM GC 동작 과정
Heap 메모리 구조
Young 영역(Young Generation)
- 새롭게 생성된 객체가 할당되는 영역
- 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라짐
- Young 영역에 대한 가비지 컬렉션(Garbage Collection)을 Minor GC라고 부른다.
- 효율적인 GC를 위해 3가지 영역으로 나눔
- Eden: new를 통해 새로 생성된 객체가 위치, GC 후 살아남은 객체들은 Survivor 영역으로 보냄
- Survivor 0 / Survivor 1: 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역, 0 or 1 둘 중 하나는 꼭 비어 있어야 함
Old 영역(Old Generation)
- Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
- Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생
- Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC 또는 Full GC라고 부른다.
Minor GC 과정
Young Generation 영역에서 발생되는 GC
- Minor GC는 Eden 영역이 가득 찬 후 실행
- Eden 영역에서 참조가 남아있는 객체를 mark하고 survivor 영역으로 복사, Eden 영역을 비움
- Survivor 영역도 가득차면 같은 방식으로 다른 Survivor 영역에 복사하고 비움
- 이를 반복하다 보면 계속해서 살아남는 객체는 old 영역으로 이동
Major GC 과정
Old Generation은 길게 살아남는 메모리들이 존재하는 공간으로 이 영역에서 발생되는 GC Stop-The-World 문제가 발생
- Old 영역은 데이터가 가득 차면 GC를 실행
- 삭제되어야 하는 객체를 mark하고 지움(sweep)
- 메모리는 단편화된 상태이므로 이를 한 군데에 모아주는 것을 Compaction이라 하며 compact라함 (Mark-Sweep-Compact 알고리즘)
Garbage Collection 알고리즘
Serial GC (-XX:+UseSerialGC)
- 가장 단순한 방식의 GC로 싱글 스레드(스레드 1개)로 동작
- 싱글 스레드로 동작하여 느리고, 그만큼 Stop The World 시간이 다른 GC에 비해 길다.
- Mark & Sweep & Compact 알고리즘 사용
- 보통 실무에서 사용하는 경우는 없음 (디바이스 성능이 안좋아서 CPU 코어가 1개인 경우에만 사용)
Parallel GC (-XX:+UseParallelGC)
- Java 8의 default GC
- Young 영역의 GC를 멀티 스레드 방식을 사용하기 때문에, Serial GC에 비해 상대적으로 Stop The World가 짧음 (Old 영역은 아님)
Parallel Old GC (-XX:+UseParallelOldGC / -XX:+ParallelGCThreads=n)
- Parallel GC는 Young 영역에 대해서만 멀티 스레드 방식을 사용했다면, Parallel Old GC는 Old 영역까지 멀티스레드 방식을 사용
- 새로운 가비지 컬렉션 청소 방식인 Mark-Summary-Compact 방식을 이용 (Old 영역도 멀티 쓰레드로 처리)
CMS GC(Concurrent Mark Sweep GC)
- Stop The World로 Java Application이 멈추는 현상을 줄이고자 만든 GC
- GC 대상을 파악하는 과정이 복잡한 여러단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높음
- 메모리 파편화 문제
G1 GC (Garbage Frist GC) (-XX:+UseG1GC)
- Java 9+의 default GC
- 현재 GC 중 Stop The World의 시간이 제일 짧음
- CMS GC를 개선하여 만든 GC로 위에서 살펴본 GC와는 다른 구조를 가짐
- Heap을 Region이라는 일정한 부분으로 동적으로 나눠서 메모리 관리
- Garbage로 가득찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어드는 효과를 얻게 되는 원리 (메모리가 많이 차있는 영역을 우선적으로 GC)
- Heap Memory 전체를 탐색하는 것이 아닌 영역(region)을 나눠 탐색하고 영역(region)별로 GC
Shenandoah GC
- Java 12에 release
- 레드 햇에서 개발한 GC
- 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결
- 강력한 Concurrency와 가벼운 GC 로직으로 heap 사이즈에 영향을 받지 않고 일정한 pause 시간이 소요가 특징
ZGC (Z Garbage Collector)
- Java 15에 release
- 대량의 메모리(8MB ~ 16TB)를 low-latency로 잘 처리하기 위해 디자인 된 GC
- G1의 Region 처럼, ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는 2mb 배수로 동적으로 운영됨 (큰 객체가 들어오면 2^ 로 영역을 구성해서 처리)
- ZGC가 내세우는 최대 장점 중 하나는 힙 크기가 증가하더도 'stop-the-world'의 시간이 절대 10ms를 넘지 않는다는 것
참고 자료:
[Java] 자바 JVM 내부 구조와 메모리 구조에 대하여
저번 포스팅에서는 JVM에 대해서 간략하게 알아보는 시간을 가졌다면 이번 포스팅에서는 JVM의 내부 구조에 대해 좀 더 자세하게 알아보도록 하겠습니다. 혹시 JVM의 정의와 왜 필요한지 궁금하시
coding-factory.tistory.com
☕ 가비지 컬렉션 동작 원리 & GC 종류 💯 총정리
Garbage Collection(GC) 이란? 가비지 컬렉션(Garbage Collection, 이하 GC)은 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객
inpa.tistory.com