JVM이란?
JVM(Java Virtual Machine)은 자바 바이트코드를 실행하기 위한 가상 머신이다. 플랫폼에 독립적인 실행 환경을 제공하며, 자바 프로그램의 실행을 책임진다.
JVM 구성 요소
- 클래스 로더 (Class Loader)
- 실행 엔진 (Execution Engine)
- 런타임 데이터 영역 (Runtime Data Area)
- 네이티브 메서드 인터페이스 (JNI)
- 네이티브 메서드 라이브러리
자바 메모리 구조
Method Area (메서드 영역)
- 클래스에 대한 메타데이터 저장: 클래스 이름, 부모 클래스, 메서드 정보, 변수 정보 등
static 변수 저장
- 모든 스레드가 공유하는 영역
- 예: static int count; → 여기에 저장됨
Heap (힙 영역)
- 객체와 배열이 저장되는 공간
- GC(Garbage Collector)의 대상이 되는 영역
- 모든 스레드가 공유함
Stack (스택 영역)
- 각 스레드마다 생성되는 공간
- 메서드 호출 시 생성되는 프레임 저장
- 지역 변수, 매개변수 저장
- 메서드 호출이 끝나면 스택 프레임이 제거됨
PC Register (프로그램 카운터)
- 현재 실행 중인 JVM 명령어의 주소를 저장
- 스레드마다 개별적으로 존재
Native Method Stack
- C/C++ 등 JVM 외의 네이티브 메서드 실행 시 사용되는 스택
JVM 동작 과정
-
클래스 로딩
.java -> .class 컴파일된 바이트코드를 JVM이 로드
- 로드, 링크, 초기화 과정 포함
-
바이트코드 검증
-
실행 엔진 동작
- 인터프리터 : 바이트코드를 한 줄씩 실행
- JIT(Just In Time) 컴파일러 : 자주 사용되는 코드를 기계어로 변환해 성능 최적화
-
GC(Garbage Collection)
- 참조되지 않는 객체를 힙에서 자동으로 제거하여 메모리 회수
Garbage Collection
자바의 장점 중 하나는 개발자가 직접 메모리를 해제하지 않아도 된다는 점이다. GC가 JVM의 Heap 영역에서 더 이상 사용되지 않는 객체를 자동으로 탐지하고 제거하기 때문이다.
객체를 생성한 후 명시적으로 메모리를 해제하기 않으면 메모리 누수가 발생하고, 이는 시스템 성능 저하나 종료로 이어질 수 있기 때문에 메모리 관리가 중요하다.
Young / Old Generation
GC는 힙을 크게 Young Generation과 Old Generation으로 나누어 관리하며, 각 영역에서 다른 방식으로 수집한다.
-
Young Generation (신생 영역)
- 새로 생성된 객체들이 저장됨(
new 키워드로 생성)
- 대부분의 객체는 이 영역에서 잠깐 사용되고 사라짐
Eden, Survivor로 나뉨
Minor GC가 발생 → 처리 속도가 빠름
-
Old Generation (노후 영역)
- Young 영역에서 오랫동안 살아남은 객체가 이동
- 오랫동안 살아있는 객체가 많음
Major GC / Full GC 발생 → 처리 시간이 길 수 있음
GC 실행 방식
- Mark and Sweep
- Mark 단계 : 참조가 남아 있는 객체에 표시
- Sweep 단계 : 표시되지 않은 객체를 제거
- Copying
- 주로 Young 영역에서 사용
- 객체를 Survivor 영역에서 복사하면서 살아있는 객체만 남기고 나머지는 제거
- Compacting
- 객체가 흩어져 있으면 접근이 느려지므로, 연속된 공간으로 재배치하여 단편화를 줄임
GC 종류
| 종류 | 설명 |
|---|
| Serial GC | 단일 스레드, 메모리가 작을 때 적합 |
| Parallel GC | 멀티 스레드, Throughput 중시 환경에 적합 |
| CMS GC | GC로 인한 정지 시간을 줄이기 위해 Concurrent 방식 사용 |
| G1 GC | 최근 JVM에서 기본값, 영역을 나눠서 효율적으로 GC 수행 |