"JVM을 블랙박스가 아닌, 완전히 해부된 기계로 이해하기"
"Java 코드를 작성하는 것과, Java 코드가 어떻게 살아 움직이는지 아는 것은 다르다"
바이트코드부터 GC 알고리즘, JIT 컴파일러, Java Memory Model까지
왜 이렇게 설계됐는가 라는 질문으로 JVM 내부를 끝까지 파헤칩니다
JVM에 관한 자료는 많습니다. 하지만 대부분은 "무엇인가" 에서 멈춥니다.
| 일반 자료 | 이 레포 |
|---|---|
| "GC는 메모리를 수거합니다" | GC Root 탐색 알고리즘과 Stop-The-World가 발생하는 정확한 시점 |
| "volatile은 가시성을 보장합니다" | 메모리 배리어가 CPU 캐시에 내리는 명령 수준까지 |
| "JIT는 코드를 최적화합니다" | Tiered Compilation 5단계, OSR, Deoptimization 메커니즘 |
| "synchronized는 무겁습니다" | Biased → Thin → Fat Lock 전이와 Mark Word 변화 |
| 이론 나열 | 실행 가능한 코드 + javap, JFR, JMH 실측 포함 |
각 챕터의 첫 문서부터 바로 학습을 시작하세요!
💡 각 섹션을 클릭하면 상세 문서 목록이 펼쳐집니다
핵심 질문:
new MyClass()를 호출하기 전, JVM은 무엇을 하는가?
클래스가 JVM에 올라오는 전체 과정 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| ClassLoader Hierarchy | Bootstrap / Extension / Application 계층과 Parent Delegation Model |
| Loading → Linking → Initializing | 3단계 책임 분리, static 초기화 블록이 실행되는 정확한 시점 |
| Bytecode Verification | JVM이 .class 파일을 어떻게 신뢰하는가, Verifier 동작 원리 |
| Symbolic Reference Resolution | ConstantPool의 심볼릭 참조가 직접 참조로 변환되는 과정 |
| Class Unloading | 클래스가 언로딩되는 조건, ClassLoader 누수와 메모리 누수 |
| Custom ClassLoader | findClass() vs loadClass(), 암호화된 클래스 런타임 복호화 |
| ClassLoader Isolation | 같은 클래스명이 두 ClassLoader에서 로드되면 == 결과는? |
핵심 질문: 내 객체는 JVM 메모리 어디에, 어떤 모습으로 존재하는가?
JVM이 메모리를 나누고 관리하는 방식 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| Heap Structure | Eden / Survivor / Old Generation 물리적 구조, 객체 이동 조건 |
| TLAB (Thread-Local Allocation Buffer) | TLAB가 없으면 생기는 경합, 스레드별 Eden 파티셔닝 원리 |
| Stack And Frames | Stack Frame 구조(LVA / Operand Stack / Frame Data), StackOverflowError 시점 |
| Method Area & Metaspace | PermGen이 사라진 이유, Metaspace OOM 시나리오 |
| Runtime Constant Pool | 클래스 파일 상수풀 vs 런타임 상수풀, 문자열 리터럴의 위치 |
| Object Layout In Memory | Object Header + Instance Data + Padding, JOL로 실측 |
| Off-Heap & Direct Memory | ByteBuffer, sun.misc.Unsafe, GC가 닿지 않는 메모리 |
핵심 질문: 내가 짠 Java 코드가 JVM의 언어로 어떻게 번역되는가?
Java 코드와 JVM 사이의 언어, 바이트코드 완전 분석 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| Class File Format | .class 파일 바이너리 구조, magic number부터 attributes까지 |
| Bytecode Instruction Set | 200+ 명령어 카테고리 분류, 타입별 명령어 분리 이유 |
| Operand Stack Mechanism | 스택 기반 VM vs 레지스터 기반 VM, 명령어가 스택에 하는 일 |
| Method Invocation Instructions | invokevirtual / invokeinterface / invokespecial / invokestatic 차이 |
| Exception Handling Bytecode | try-catch-finally가 bytecode에서 Exception Table로 변환되는 방식 |
| Lambda & InvokeDynamic | Lambda가 내부 클래스가 아닌 이유, LambdaMetafactory 동작 원리 |
| Bytecode Manipulation (ASM) | ASM으로 런타임에 바이트코드 조작, AOP 구현 원리 |
핵심 질문: JVM은 bytecode를 어떻게 "빠르게" 실행하는가?
Interpreter에서 JIT까지, 코드가 실행되는 방식의 진화 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| Interpreter Mechanism | Template Interpreter 구조, bytecode → 기계어 디스패치 테이블 |
| JIT Compilation Basics | Warm-up 임계값, 컴파일 대상 선정 기준 (-XX:+PrintCompilation) |
| Tiered Compilation | Level 0~4 전환 조건, C1 / C2 컴파일러 역할 분리 |
| JIT Optimizations | Inlining, Escape Analysis, Loop Unrolling, Dead Code Elimination |
| On-Stack Replacement (OSR) | 이미 실행 중인 메서드를 JIT 버전으로 교체하는 메커니즘 |
| Deoptimization | Speculative Optimization 실패 시 Interpreter로 복귀하는 과정 |
| JVM Intrinsics | JVM이 특정 메서드를 CPU 명령어로 직접 대체하는 방식 |
핵심 질문: JVM은 어떻게 "죽은 객체"를 판단하고, 어떻게 제거하는가?
Serial GC부터 ZGC까지, GC 알고리즘의 진화와 원리 (11개 문서)
| 문서 | 다루는 내용 |
|---|---|
| GC Roots & Reachability | GC Root 종류, 순환 참조가 왜 문제가 안 되는가 |
| Reference Types | Strong / Soft / Weak / Phantom Reference별 GC 동작, WeakHashMap |
| Mark-Sweep-Compact | 3단계 알고리즘, Fragmentation 문제와 Compaction 비용 |
| Generational Hypothesis | "대부분의 객체는 젊어서 죽는다"는 가설이 GC 설계에 미친 영향 |
| Serial & Parallel GC | 단순 GC 동작 원리, Stop-The-World 비용 |
| CMS GC & Problems | Concurrent Mark의 혁신과 Concurrent Mode Failure 한계, G1 탄생 배경 |
| G1 GC Deep Dive | Region 기반 구조, Concurrent Marking → Evacuation, Pause Prediction Model |
| ZGC Deep Dive | Colored Pointer, Load Barrier, Concurrent Relocation — pause < 1ms 원리 |
| Shenandoah GC | Brooks Pointer, ZGC와의 설계 철학 차이 |
| GC Tuning Flags | 실전에서 쓰는 JVM 플래그 완전 정리 |
| GC Log Analysis | -Xlog:gc* 로그 해석, STW 시간 측정, 메모리 누수 탐지 |
핵심 질문: 멀티코어 CPU에서 Java 코드는 왜 예상과 다르게 동작하는가?
CPU 캐시부터 Happens-Before까지, 동시성의 근본 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| CPU Cache & Visibility Problem | 캐시 계층 구조, 명령어 재정렬, JMM이 이 모든 것을 추상화하는 이유 |
| Happens-Before | HB 규칙 8가지, "실행 순서"와 "가시성 보장 순서"가 다른 이유 |
| Volatile Deep Dive | volatile이 보장하는 것(가시성 + 재정렬 금지)과 보장 안 하는 것(원자성) |
| Final Field Semantics | 생성자 완료 후 final 필드가 보장되는 범위, 안전한 불변 객체 공개 |
| Publication & Escape | 객체가 "탈출"하는 경우, 안전한 공개(Safe Publication) 패턴 |
| Synchronized Internals | synchronized가 삽입하는 Memory Barrier, 모니터 락의 메모리 의미론 |
| Memory Barriers | LoadLoad / StoreStore / LoadStore / StoreLoad 배리어와 CPU 명령어 |
핵심 질문:
synchronized와ReentrantLock은 내부에서 어떻게 다른가?
Lock 메커니즘과 스레드 스케줄링의 실제 구현 (9개 문서)
| 문서 | 다루는 내용 |
|---|---|
| Object Monitor | Monitor 구조, Entry Set / Wait Set, wait() / notify() 내부 동작 |
| Lock: Biased → Thin → Fat | Mark Word 변화로 보는 Lock 상태 전이, Biased Lock deprecated 이유 |
| CAS & Atomic Operations | CPU의 CMPXCHG 명령어, ABA 문제, AtomicInteger 내부 구현 |
| False Sharing & Cache Line | 64바이트 캐시라인, @Contended, JMH로 False Sharing 실측 |
| AQS Internals | CLH Queue, ReentrantLock / Semaphore / CountDownLatch 공통 기반 |
| Thread States & Scheduler | OS 스레드 상태 vs JVM 스레드 상태, Context Switching 비용 |
| ThreadLocal Internals | ThreadLocalMap 내부 구조, 메모리 누수 발생 조건 |
| Virtual Threads (Project Loom) | Carrier Thread, Structured Concurrency, pinning 주의사항 |
| Safepoint Mechanism | Safepoint가 필요한 이유, Time-To-Safepoint 지연 원인과 분석 |
핵심 질문: JVM을 어떻게 측정하고, 어떻게 최적화하는가?
JFR, async-profiler, JMH로 JVM을 실측하고 개선하는 방법 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| JVM Flags Complete Guide | 실전에서 쓰는 플래그 전체 정리 (-Xms, -Xmx, -XX:*) |
| Heap Sizing Strategy | Initial / Max Heap 비율, Young/Old 비율, 컨테이너 환경 주의사항 |
| GC Ergonomics | JVM이 스스로 GC와 힙 크기를 조정하는 자동 튜닝 원리 |
| Profiling with JFR | Java Flight Recorder + JDK Mission Control, Flame Graph 읽기 |
| Profiling with async-profiler | CPU / 메모리 / 락 프로파일링, alloc 모드로 GC 압박 찾기 |
| Memory Leak Analysis | Heap Dump 분석, 누수 패턴 (static, ThreadLocal, ClassLoader) |
| Benchmarking with JMH | 왜 System.nanoTime()은 부정확한가, Warm-up / Blackhole / @State |
핵심 질문: JVM이 숨기고 있는 더 깊은 층에는 무엇이 있는가?
Mark Word, Compressed Oops, Java Agent까지 — JVM의 가장 깊은 곳 (7개 문서)
| 문서 | 다루는 내용 |
|---|---|
| Object Header & Mark Word | 64비트 Mark Word 레이아웃, 해시코드 / Lock 상태 / GC 나이 필드 |
| Compressed Oops | 64비트 JVM에서 포인터를 32비트로 압축하는 원리, 32GB 힙 제한 이유 |
| String Pool & Interning | 문자열 상수풀 위치 변화 (PermGen → Heap), intern() 비용 |
| Unsafe API | sun.misc.Unsafe로 직접 메모리 조작, JDK 내부 코드가 쓰는 이유 |
| Reflection & Performance | Reflection 호출 경로, 15회 임계값 후 바이트코드 생성, JIT와의 관계 |
| Instrumentation & Java Agent | -javaagent 동작 원리, ClassFileTransformer로 클래스 변환 |
| JNI Internals | JVM ↔ Native 코드 경계, JNI 호출 비용, Global / Local Reference |
🟢 Java 개발을 시작하는 분 / 기술 면접 준비 (3~4주)
Week 1 — JVM 메모리 구조 확립
heap-structure
stack-and-frames
object-layout-in-memory
method-area-metaspace
Week 2 — GC 원리 이해
gc-roots-and-reachability
generational-hypothesis
g1-gc-deep-dive
gc-log-analysis
Week 3 — 동시성과 JMM
cpu-cache-and-visibility-problem
happens-before
volatile-deep-dive
lock-biased-thin-fat
Week 4 — 실전 튜닝
jvm-flags-complete-guide
heap-sizing-strategy
benchmarking-with-jmh
🔵 Java 코드를 원리로 이해하고 싶은 개발자 (6~8주)
class-loading 전체
→ runtime-data-areas 전체
→ bytecode 전체 (javap로 직접 분석)
→ execution-engine 전체 (JIT 동작 실측)
→ garbage-collection 전체
🔴 JVM 마스터 목표 (3~4개월)
전체 순서대로 + code/ 예제 직접 실행
→ advanced-internals 챕터로 마무리
→ JFR + async-profiler로 실제 프로젝트 분석
모든 문서는 동일한 구조로 작성됩니다.
| 섹션 | 설명 |
|---|---|
| 🎯 핵심 질문 | 이 문서를 읽고 나면 답할 수 있는 질문 |
| 🔍 왜 이게 존재하는가 | 문제 상황과 설계 배경 |
| 📐 내부 구조 | 원리 + 다이어그램 |
| 💻 실험으로 확인하기 | 직접 실행 가능한 코드 + 예상 결과 + 측정 도구 |
| ⚡ 실무 임팩트 | 이 지식이 실제 코드 작성 / 장애 대응에 어떤 영향을 주는가 |
| 🚫 흔한 오해 | 잘못 알려진 내용 교정 |
| 📌 핵심 정리 | 한 화면 요약 |
- Java Virtual Machine Specification (JVMS)
- Inside the Java Virtual Machine — Bill Venners
- The Garbage Collection Handbook — Richard Jones
- JEP Index
- OpenJDK Source Code
⭐️ 도움이 되셨다면 Star를 눌러주세요!
Made with ❤️ by Dev Book Lab
"Java 코드를 작성하는 것과, Java 코드가 어떻게 살아 움직이는지 아는 것은 다르다"