The JVM and its memory model
Java code is not run by the CPU directly. javac compiles source into portable bytecode (.class), and a per-platform JVM loads that bytecode, checks it for correctness, interprets it instruction by instruction, and JIT-compiles hot spots to native code. That is exactly why the same .class runs on Windows, Linux, and macOS — the artifact is portable; the machine beneath it is not.
The second half of the topic is how the JVM manages memory at runtime. Objects live on a heap shared across all threads and are freed automatically by garbage collection, while method frames holding local variables live on a stack private to each thread that grows and shrinks by itself on calls and returns. Understanding this split turns OutOfMemoryError, StackOverflowError, and GC pauses from "magic" into predictable consequences. The full map lives in the layers below.
Topic map
- JVM vs JRE vs JDK — which is the engine, which the runtime, which the developer kit; the
JDK ⊃ JRE ⊃ JVMnesting. - Platform independence — "write once, run anywhere": portable bytecode plus a per-platform JVM.
- Bytecode — what the
.classformat holds, how to read it withjavap, and the role of theJIT. - JVM execution — a class's path: classloader → verification → interpret/JIT.
- Memory areas — heap, thread stacks, metaspace, PC registers; what is shared and what is per-thread.
- Heap vs stack — where objects live, where frames live, and why one is collected while the other is popped.
- Garbage collection — reachability, generations, the throughput-versus-pause trade-off.
Common traps
| Mistake | Consequence |
|---|---|
Thinking you need the full JDK just to run a .class | The JDK is needed to build; the JRE (JVM + libraries) runs an application |
| Calling bytecode "native machine code" | Bytecode is portable; the JVM/JIT turns it into native code for the specific hardware |
| Assuming the JVM compiles the whole class up front like a C compiler | The JVM interprets first and JIT-compiles only hot methods at runtime |
| Putting objects on the stack and class metadata on the heap | Objects always live on the heap; class metadata lives in the method area (metaspace) |
Treating the stack as garbage-collected | A frame is freed by a simple pop on return; GC works only over the heap |
| Believing automatic memory makes leaks impossible | A reachable-but-unneeded object (a forgotten reference) is never collected — that is a leak |
Expecting GC to free an object the instant it becomes unreachable | Collection timing is non-deterministic — you cannot predict the moment of release |
Interview relevance
The JVM model comes up on almost every Java interview — not as acronym recall, but as a test of whether you picture what happens between your code and the hardware. A candidate who explains startup as "the classloader loads the .class, the verifier checks it, then interpretation plus JIT on hot methods" immediately stands out from "well, Java just runs the bytecode".
Typical checks:
- The difference between JVM / JRE / JDK and how they nest.
- Why the bytecode is portable while the JVM itself is platform-specific.
- Hybrid execution: interpretation plus JIT compilation of hot methods.
- Which memory areas are shared across threads (heap, method area) and which are per-thread (stacks, PC registers).
- How the heap differs from the stack, and why
StackOverflowErroris not about the heap. - What garbage collection does, what it trades for automation, and when an object still leaks.
Common wrong answer: "The JVM compiles Java to machine code, like C." That opens the discussion that javac produces portable bytecode rather than native code, that each platform ships its own JVM, and that code becomes native only for hot methods via the JIT at runtime.