JVM이 정확히 무엇이고, 어떤 기능을 하는지 설명해 주세요.
Java 바이트코드를 운영체제에 독립적으로 실행할 수 있게 해주는 가상 머신입니다.
JVM이 필요한 이유
일반적인 컴파일 언어(C, C++)는 OS·CPU마다 다른 기계어로 컴파일해야 합니다. Java는 소스코드 → 바이트코드(.class) 로 한 번만 컴파일하고, 각 플랫폼의 JVM이 이를 해석·실행하므로 "Write Once, Run Anywhere" 가 가능합니다.
전체 실행 흐름
Hello.java
│ javac (컴파일)
▼
Hello.class (바이트코드)
│ java 명령어
▼
┌──────────────── JVM ────────────────┐
│ Class Loader → Runtime Data Area │
│ → Execution Engine │
└─────────────────────────────────────┘
│
▼
OS / 하드웨어
JVM 내부 구조
1. Class Loader (클래스 로더)
.class 파일을 로딩 → 링크 → 초기화 3단계로 메모리에 적재합니다.
| 단계 | 설명 |
|---|---|
| Loading | .class 파일을 읽어 바이너리 데이터 생성 |
| Linking | 검증(Verify) → 준비(Prepare) → 해석(Resolve) |
| Initialization | static 변수 할당, static 블록 실행 |
2. Runtime Data Area (메모리 영역)
| 영역 | 공유 범위 | 저장 내용 |
|---|---|---|
| Method Area | 모든 스레드 | 클래스 메타정보, static 변수, 상수 풀 |
| Heap | 모든 스레드 | new로 생성된 객체·배열 (GC 대상) |
| Stack | 스레드별 | 지역 변수, 매개변수, 리턴 값, 프레임 |
| PC Register | 스레드별 | 현재 실행 중인 명령어 주소 |
| Native Method Stack | 스레드별 | JNI를 통한 네이티브 메서드 정보 |
3. Execution Engine (실행 엔진)
바이트코드를 실제 기계어로 변환·실행합니다.
| 구성 요소 | 역할 |
|---|---|
| Interpreter | 바이트코드를 한 줄씩 해석·실행 (초기 속도 빠름) |
| JIT Compiler | 반복 호출되는 코드(핫스팟)를 네이티브 코드로 일괄 변환 (실행 속도 향상) |
| Garbage Collector | Heap 영역에서 참조되지 않는 객체를 자동 회수 |
JVM vs JRE vs JDK
┌─────────────────── JDK ───────────────────┐
│ javac, jdb, jar 등 개발 도구 │
│ ┌──────────── JRE ────────────┐ │
│ │ Java 표준 라이브러리 │ │
│ │ ┌─────── JVM ───────┐ │ │
│ │ │ 실행 엔진 + 메모리 │ │ │
│ │ └───────────────────┘ │ │
│ └────────────────────────────┘ │
└───────────────────────────────────────────┘
| 구분 | 포함 관계 | 용도 |
|---|---|---|
| JVM | 최소 단위 | 바이트코드 실행 |
| JRE | JVM + 라이브러리 | Java 프로그램 실행 |
| JDK | JRE + 개발 도구 | Java 프로그램 개발 |
핵심 정리
JVM의 주요 기능은 크게 네 가지입니다. 첫째 플랫폼 독립성으로, 바이트코드를 각 OS에 맞게 변환합니다. 둘째 메모리 관리로, GC를 통해 개발자가 직접 메모리를 해제하지 않아도 됩니다. 셋째 보안으로, 바이트코드 검증과 샌드박스를 통해 악성 코드 실행을 방지합니다. 넷째 최적화로, JIT 컴파일러가 런타임에 성능을 개선합니다.