
JVM(Java Virtual Machine)은 Java 바이트코드(.class)를 실행하는 가상 머신이다.
Java는 운영체제에 직접 실행되지 않고

위와 같은 구조를 가지기 때문에
어느 운영체제에서도 동일한 Java 프로그램 실행이 가능하다.
Write Once, Run Anywhere의 핵심
JVM은 JRE(Java Runtime Environment)의 핵심 구성 요소이며,
JRE = JVM + Java 표준 라이브러리라고 볼 수 있다.

.class 파일을 필요한 시점에 메모리로 로드
자바 클래스 파일은 JVM이 이해할 수 있는 표준 포맷을 가진다.
| 항목 | 설명 |
|---|---|
| Magic Number | 0xCAFEBABE – 자바 클래스 파일 식별 |
| 버전 정보 | 컴파일된 Java 버전 |
| Constant Pool | 클래스/메서드/필드 참조 저장 |
| Access Flags | public, abstract, final 등 |
| Class / Super Class | 자신과 부모 클래스 정보 |
| Interfaces | 구현한 인터페이스 |
| Fields | 멤버 변수 |
| Methods | 메서드 |
| Attributes | 디버깅 정보, 애노테이션 등 |
JVM은 모든 클래스를 한 번에 로딩하지 않는다.
→ 클래스를 컴파일 시점이 아니라 실행 중에 로딩
→ 동적 클래스 로딩
Class.forName()ClassLoader.loadClass()지연 로딩(Lazy Loading)
클래스가 참조 가능 상태에 있어도
실제로 사용되기 전까지 로드하지 않는 방식
- JVM의 메모리 최적화 전략
- 로드할 수 있다 ≠ 지금 당장 로드한다
- 정말 필요해질 때까지 미룬다
왜 동적 로딩이 중요할까?

Loading 과정에서 파일을 업로드할 때 각각의 .class 파일들이 기본으로 제공받은 파일인지 개발자가 정의한 파일인지 등에 따라 맞는 클래스 로더에 따라 로딩
.class 파일을 읽어 메모리에 적재java.lang.Class 객체 생성로드된 .class 파일들을 사용하기 위해 검증하고 준비하는 과정
Verification(검증)
JVM에서 사용이 가능한 형태인지 검증
VerifyErrorPreparation(준비)
클래스가 필요로 하는 메모리 할당, 클래스의 필드, 메서드, 인터페이스를 나타내는 데이터 구조 준비
0, null)Resolution(분석)
JVM의 할당된 메모리 참조를 Method Area에 참조된 메모리 주소 값으로 바꾸는 단계
.class 파일의 코드를 읽어 Java 코드에서의 class와 interface의 값들을 지정한 값들로 초기화하고 method 실행

Bootstrap Class Loader
JVM을 실행시키기 위한 필수 라이브러리 로드
java.lang, java.util 등 핵심 클래스Extension Class Loader
Bootstrap ClassLoader를 부모로 갖는 클래스 로더로 확장 자바 클래스 로드
JAVA_HOME/lib/ext 경로Application Class Loader
어플리케이션 레벨의 클래스 로드
Custom Class Loader
클래스 로딩
→ 링킹
→ 초기화
→ main() 실행
→ 객체 생성
→ 메서드 호출
→ 종료
Runtime Data Area는 JVM이 자바 프로그램을 실행하면서 사용하는 메모리 영역이다.
크게 스레드 공유 영역과 스레드 전용 영역으로 나뉜다.

구분이 중요한 이유

JVM이 클래스(.class)를 로드할 때, 클래스 레벨 정보를 저장하는 영역이다.
저장되는 대표 정보
흔히 Class Area, Static Area라고도 부른다.
차이 핵심
| Method Area | Metaspace |
|---|---|
| JDK8 이후부터 삭제 | JDK8부터 도입 |
| 항상 최대 크기가 고정 | 기본 OS에 따라 자동으로 크기를 늘림 |
| 연속적인 Java Heap 메모리 | 기본 OS에서 제공하는 메모리 |
| 비효율적인 Garbage Collection | 효율적인 Garbage Collection |
Method Area 내부에 포함되는 클래스별 상수/참조 테이블 느낌이다.
여기에 들어가는 것
JVM은 실행 중 참조가 필요하면
힙은 런타임에 생성되는 객체(인스턴스), 배열 같은 참조 타입 데이터가 저장되는 영역이다.
new로 생성되는 대부분은 Heap에 저장됨
힙에 있는 객체 자체를 직접 다루는 게 아니라,
Person p = new Person();
new Person() 객체 → Heapp 참조 변수 → Stack (그리고 Heap 객체를 가리킴)→ 참조가 끊기면 GC 대상
힙을 효율적으로 관리하기 위해 세대(Generation) 개념을 쓴다.
Young Generation
생명주기 짧은 객체가 많아서 자주 GC가 발생하는 영역
Old Generation
Young에서 오래 살아남은 객체가 올라오는 곳
여기는 GC가 상대적으로 덜 자주 일어나지만, 한 번 할 때 비용이 큼.
스택은 메서드 호출 단위로 생성되는 실행 프레임을 저장한다.
스레드마다 하나씩 존재하고, 스레드 종료 시 같이 사라진다.
메서드가 호출될 때마다 Frame이 생기고, 종료되면 제거된다.
Frame 안에는 보통
스택은 크기가 제한되어 있어서
재귀 호출이 너무 깊거나, 프레임이 과도하게 쌓이면 StackOverflowError 발생 가능.
PC Register는 각 스레드가 지금 실행 중인 바이트코드 명령 위치를 기억하는 곳이다.
왜 필요?
→ PC Register는 JVM 관점의 실행 커서

Java 코드가 아니라 JNI를 통해 호출된 네이티브 코드(C/C++ 등)를 실행할 때
그 호출 스택을 관리하는 영역이다.
흐름 예시
native 메서드 호출 → Native Method Stack 사용실행 엔진을 통해 Runtime Data Area에 있는 바이트 코드를 기계어로 변환해서 실행
바이트 코드를 한줄 한줄 해석하고 실행
인터프리터의 속도 문제를 해결하기 위해 디자인된 기능
JVM은 이 두 방식을 결합해서 사용
→ 프로그램이 처음 실행될 때는 인터프리터를 통해 빠르게 실행되지만
→ 일정한 코드 블록이나 메서드가 자주 실행되는 경우엔 JIT 컴파일러를 통해 최적화