JVM Architecture
ClassLoader, runtime data areas (heap/stack/metaspace), execution engine, JIT compiler
The Java Virtual Machine (JVM) is the engine that runs Java bytecode. It abstracts the underlying hardware and OS, enabling "write once, run anywhere." Understanding the JVM's internals — how it loads classes, manages memory, and executes code — is essential for writing high-performance Java and diagnosing production issues.
Key Points
- ClassLoader subsystem loads .class files into memory in three phases: Loading → Linking → Initialization
- Bootstrap ClassLoader (JVM built-in) loads core Java classes (java.lang, java.util)
- Extension / Platform ClassLoader loads JDK extension classes; Application ClassLoader loads your app classpath
- Heap: shared memory for all objects — divided into Young Generation (Eden + Survivor spaces) and Old Generation (Tenured)
- Stack: per-thread, stores stack frames (local variables, operand stack, method references) — not garbage collected
- Metaspace (Java 8+): replaces PermGen; stores class metadata in native memory — grows automatically by default
- PC Register: per-thread pointer to the current JVM instruction being executed
- JIT Compiler: C1 (client — fast compile) and C2 (server — optimised machine code) — hot methods get compiled
- HotSpot JVM identifies "hot" code via profiling and replaces bytecode interpretation with native machine code
JVM Architecture: ClassLoader feeds bytecode into runtime data areas; the Execution Engine interprets or JIT-compiles and GCs memory
| Area | Scope | Stores | GC'd? |
|---|---|---|---|
| Heap | All threads | Objects, arrays | Yes |
| Metaspace | All threads | Class metadata, static fields (Java 8+) | On class unload |
| JVM Stack | Per thread | Stack frames, local vars, operand stack | No (auto on return) |
| PC Register | Per thread | Current bytecode instruction address | No |
| Native Method Stack | Per thread | JNI native method frames | No |
Real-World Example
OutOfMemoryError: Java heap space → heap too small or memory leak. OutOfMemoryError: Metaspace → too many dynamically generated classes (e.g. CGLIB proxies, Groovy scripts). StackOverflowError → unbounded recursion. Understanding which area is exhausted tells you exactly which JVM flag to tune (-Xmx, -XX:MaxMetaspaceSize, -Xss).