JVM Internals & Memory
JVM Architecture
- Pipeline: class loading → bytecode verification → interpretation → profiling → JIT compilation
- Major subsystems: class loader, runtime data areas (heap, stacks, metaspace), execution engine (interpreter + JIT), GC
- HotSpot optimizes the common path based on observed runtime behavior — often beating static compilation
- Java's two value kinds: primitives and object references — no raw pointers
java -XX:+PrintFlagsFinalreveals the ~700 tunables; most should stay untouched
The design bet of the managed runtime (Optimizing Java ch. 2): accept an abstraction layer between code and CPU, and repay it with runtime knowledge no static compiler has — which branches are actually taken, which types actually flow, which locks are actually contended. The interpreter starts instantly; the JIT (Jit Compilation) recompiles hot methods with profile-guided aggression; GC (Gc Fundamentals) replaces manual memory management with throughput-tuned automation.
| Area | Holds | Per | Failure mode |
|---|---|---|---|
| Heap | all objects and arrays | JVM | OutOfMemoryError: Java heap space |
| Java stacks | frames: locals, operand stack, return addresses | thread | StackOverflowError |
| Metaspace | class metadata (native memory since Java 8) | JVM | OOME: Metaspace |
| Code cache | JIT-compiled machine code | JVM | JIT stops compiling (silent slowdown) |
| Native/direct | direct ByteBuffers, thread stacks, JNI | JVM/OS | RSS growth invisible to heap monitoring |
A running JVM is a multithreaded native process: your application threads share the process with JIT compiler threads, GC worker threads, and service threads (signal dispatch, attach listener). "The application is idle but CPU is busy" frequently means GC or JIT activity — visible with jcmd/JFR (Profiling).
$ java -XX:+PrintFlagsFinal -version | grep -i maxheap // effective flag values
$ jcmd <pid> VM.flags // a live process's flags
$ jcmd <pid> VM.version
$ jcmd <pid> GC.heap_info