JVM (Java Virtual Machine)은 자바 바이트 코드(.class 파일)를 실행할 수 있게 해주는 가상의 컴퓨터(추상화된 기계)다.
쉽게 말하면, "운영체제와 자바 프로그램 사이에서 중재자 역할을 하는 프로그램" 인 것이다.
자바는 “한 번 작성하면 어디서든 실행된다 (Write Once, Run Anywhere)” 는 철학을 가진 언어다. 이걸 가능하게 해주는 핵심이 바로 JVM인 것이다. 자바 코드는 컴파일 되면 바이트 코드(.class)가 되는데, 이 바이트 코드를 운영체제에서 직접 실행할 수 없기 때문에 운영체제에 맞는 JVM이 대신 실행해준다.

| 단계 | 설명 |
|---|---|
Java source code (.java) | 개발자가 작성한 코드 |
⬇ 컴파일 (javac) | 자바 컴파일러 |
Bytecode (.class) | JVM만 이해할 수 있는 중간 언어 |
⬇ 실행 (java) | JVM이 바이트코드를 실행 |
| 실제 실행됨 | JVM이 OS 위에서 실행해줌 |
JVM은 자바 프로그램을 실행하기 위해 아래의 역할을 수행한다.
.class 파일을 메모리에 올리는 역할 (ClassLoader)
JVM은 크게 아래 3가지로 나뉜다.
.class 파일 바이트 코드)을 읽어서 Runtime Data Area 형태로 메모리에 적재하는 역할을 한다.
| 영역 | 설명 |
|---|---|
| Heap Area | 동적으로 생성된 객체와 배열이 저장되는 곳으로 GC의 대상이 되는 영역 |
| Stack Area | 지역 변수, 파라미터 등이 생성되는 영역으로, 동적으로 객체를 생성하면 실제 객체는 Heap에 할당되고 해당 레퍼런스만 Stack에 저장 |
| Method Area | 클래스 멤버 변수, 메서드 정보, 타입 정보 등이 생성 |
| PC Register | 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장 |
| Native Method Stack | 자바 외의 언어로 작성된 네이티브 코드를 위한 메모리 영역 |
JVM Runtime Data Area 에 배치된 바이트 코드는 Execution Engine에 의해 실행된다.
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
javac Hello.java로 컴파일하면 → Hello.class 생성됨Hello.class 파일을 메모리에 로드하고main 메서드를 찾은 후System.out.println()을 실행한다.
여기서 “Garbage” 란 무엇일까? 바로 “정리되지 않은 메모리”, “유효하지 않은 메모리 주소” 를 뜻한다. 아래 코드를 살펴보자.
String arr = new String[3];
arr[0] = '0';
arr[1] = '1';
arr[2] = '2';
arr = new String[] {'A', 'B', 'C'};
arr 라는 배열에 문자 ‘0’, ‘1’, ‘2’ 는 어디로 간 걸까? 이런 식으로 주소를 잃어버려서 사용할 수 없는 메모리를 “정리되지 않은 메모리” 라고 할 수 있다. 추가적으로 앞으로 사용하지 않고 메모리를 가지고 있는 객체 역시 Garbage에 포함된다.
new 키워드로 객체를 생성하면 → Heap 영역에 저장됨즉, 개발자가 free()나 delete를 직접 호출할 필요가 없는 것이다. (C 언어와의 큰 차이점)
| 기능 | 설명 |
|---|---|
| 바이트 코드 실행 | 자바 코드(.class)를 실제로 실행 |
| 메모리 관리 | Stack, Heap, Method Area 등 관리 |
| GC 수행 | 사용 안 하는 객체 자동 삭제 |
| OS 독립성 제공 | 어떤 운영체제에서든 자바 프로그램 실행 가능 |
| 보안 | 바이트 코드 검증 등 다양한 보호 장치 |