Programming
JVM 구조에 대해서 설명해주세요
클래스 로더부터 런타임 데이터 영역, 실행 엔진까지. Java 코드가 실행되는 원리를 인터랙티브 시각화로 체험하며 면접에서 묻는 JVM의 핵심을 완벽히 준비합니다.
2026년 3월 15일 · 약 13분 읽기
Q. "JVM의 구조와 Java 코드가 실행되는 과정을 설명해주세요."
예상 꼬리질문
답변 가이드
"JVM은 클래스 로더 → 런타임 데이터 영역 → 실행 엔진 세 부분으로 구성됩니다. .class 파일을 메모리에 올리고, 저장하고, 실행합니다."
"메모리는 스레드 공유 영역인 Heap(객체 저장, GC 대상)과 Metaspace(클래스 메타데이터), 스레드 독립 영역인 Stack(메서드 실행 단위)으로 나뉩니다."
"실행 엔진은 인터프리터로 시작하다가, 자주 실행되는 Hot Code를 JIT 컴파일러가 네이티브 코드로 변환해 성능을 끌어올립니다."
OutOfMemoryError: Java heap space와 StackOverflowError는 왜 다른 오류일까요? JVM 내부 구조를 알면 이 차이가 즉시 이해됩니다.
이 아티클에서는 면접의 꼬리질문 흐름을 따라가며, 각 개념을 직접 만져볼 수 있는 시각화로 체험합니다.
1. JVM 전체 구조 — 세 개의 엔진
꼬리질문: "JVM의 전체 구조를 세 부분으로 나눠 설명해주세요"
JVM은 .class 파일을 받아 운영체제에서 실행할 수 있는 기계어로 변환하는 가상 머신입니다.
클래스 로더 서브시스템은 .class 파일을 메모리에 올리고, 런타임 데이터 영역은 실행 중 모든 데이터를 저장하며, 실행 엔진은 바이트코드를 실제로 실행합니다. 이 세 부분이 유기적으로 협력해 "Write Once, Run Anywhere"를 실현합니다.
아래에서 JVM 전체 구조를 직접 탐색해 보세요.
각 영역을 클릭하면 역할 설명이 표시됩니다
2. 클래스 로더 — 부모 위임 모델
꼬리질문: "클래스 로더의 부모 위임 모델이 무엇인지 설명해주세요"
.class 파일을 메모리에 올리는 클래스 로더는 로딩 → 링킹 → 초기화 순서로 동작합니다.
중요한 것은 부모 위임 모델(Parent Delegation Model)입니다. 클래스 로드 요청이 오면 자식 로더는 부모에게 먼저 위임합니다. Bootstrap → Extension → Application 순으로 시도하고, 부모가 못 찾을 때만 자식이 직접 로드합니다. 덕분에 커스텀 java.lang.String으로 핵심 클래스를 덮어쓰는 공격을 원천 차단합니다.
클래스 로드 요청의 위임 흐름을 직접 시뮬레이션해 보세요.
3. 런타임 데이터 영역 — 메모리 구조
꼬리질문: "Heap과 Stack의 차이, 그리고 Metaspace는 무엇인가요?"
JVM의 메모리는 스레드 공유 영역과 스레드 독립 영역으로 나뉩니다.
Heap은 객체를 저장하는 GC 대상 영역이고, Metaspace는 클래스 메타데이터와 static 변수를 저장합니다. Java 8부터 PermGen(고정 크기)이 Metaspace(네이티브 메모리, 동적 확장)로 교체되었습니다. Stack은 스레드마다 독립적으로 메서드 호출마다 스택 프레임이 생성·소멸됩니다.
각 메모리 영역에 데이터가 어떻게 저장되는지 확인해 보세요.
각 영역을 클릭하면 역할과 발생 가능한 에러를 확인할 수 있습니다
4. 스택 프레임 — 메서드 실행의 단위
꼬리질문: "StackOverflowError와 OutOfMemoryError의 차이가 뭔가요?"
메서드가 호출될 때마다 Stack에 스택 프레임이 생성되고, 반환되면 제거됩니다. 스택 프레임은 Local Variable Array(파라미터·지역 변수), Operand Stack(연산 작업 공간), Frame Data(상수 풀 참조·반환 주소)로 구성됩니다.
재귀 호출이 너무 깊어지면 스택 프레임이 무한 생성되어 StackOverflowError가 발생합니다. 이는 Heap이 아닌 Stack 영역 고갈이므로 OutOfMemoryError: Java heap space와 완전히 다른 문제입니다.
메서드 호출 시 스택 프레임 생성·소멸 과정을 직접 시뮬레이션해 보세요.
• Local Variable Array (지역변수)
• Operand Stack (연산 임시공간)
• Frame Data (반환 주소)
5. 실행 엔진 — 인터프리터와 JIT 컴파일러
꼬리질문: "JIT 컴파일러는 어떻게 성능을 개선하나요?"
실행 엔진은 인터프리터와 JIT 컴파일러를 조합합니다. 인터프리터는 바이트코드를 한 줄씩 해석해 즉시 실행하므로 시작은 빠르지만 반복 실행 시 느립니다.
JIT 컴파일러는 10,000번 이상 실행된 Hot Code를 감지해 전체를 네이티브 코드로 컴파일하고 캐시합니다. HotSpot JVM은 C1(빠른 컴파일) → C2(공격적 최적화) 2단계 JIT를 사용합니다.
인터프리터와 JIT 컴파일러의 성능 차이를 시뮬레이션해 보세요.
면접 체크리스트
이 항목들을 자신 있게 설명할 수 있다면 JVM 구조 질문은 준비 완료입니다.
- - JVM 3대 구성: 클래스 로더(로드) → 런타임 데이터 영역(저장) → 실행 엔진(실행)
- - 메모리 영역: Heap(객체, GC 대상) / Stack(스레드별, 메서드 실행) / Metaspace(클래스 메타데이터)
- - 부모 위임 모델: Bootstrap → Extension → Application 순 위임, 핵심 클래스 보호
- - 에러 진단: OutOfMemoryError → Heap 부족 / StackOverflowError → Stack 부족(무한 재귀)
- - JIT 컴파일: Hot Code를 네이티브 코드로 변환하여 워밍업 후 고성능 달성
참고 자료
- Naver D2 — JVM Internal — JVM 내부 구조를 한국어로 상세히 설명한 Naver 기술 블로그
- Baeldung — Java Stack vs Heap — Stack과 Heap의 차이를 코드 예제와 함께 설명
- Oracle — JVM Specification — JVM 공식 스펙 문서. 바이트코드 명령어와 런타임 동작의 원본 정의
의견을 들려주세요
서비스 개선에 큰 도움이 됩니다. 익명으로 자유롭게 남겨주세요.