Q30 of 40 · Core Java

Walk through the JVM memory model — heap, stack, method area, and metaspace.

Core JavaSeniorjvmmemoryheapmetaspaceperformanceoom

Short answer

Short answer: The JVM divides memory into several distinct runtime data areas. The heap stores all object instances and is garbage-collected. Each thread owns a private stack holding frames (local variables, operand stack, return address) — one frame per method invocation. The method area (pre-Java 8) / metaspace (Java 8+) stores class metadata, bytecode, and the constant pool. The PC register and native method stack round out the per-thread areas.

Detail

Heap Shared across all threads. Split (in G1/ZGC/Shenandoah) into regions or generations. Holds all new objects and arrays. Subject to GC pauses.

Stack (per thread) LIFO. Each method call pushes a frame; the frame holds:

  • Local variable array (primitives stored directly; object references point into the heap)
  • Operand stack (working area for bytecode instructions)
  • Reference to the constant pool of the current class StackOverflowError = recursion too deep.

Metaspace (Java 8+, replaced PermGen) Off-heap (native memory). Stores class metadata, method bytecode, field descriptors, vtables. Grows dynamically; bounded by -XX:MaxMetaspaceSize. OutOfMemoryError: Metaspace = class-loading leak (common in frameworks that generate classes at runtime, e.g., reflection-heavy proxies).

Code cache JIT-compiled native code lives here, not on the heap.

JVM Runtime Data Areas
┌─────────────────────────────────────────────┐
│  Heap (shared)                              │
│   Young gen: Eden + S0 + S1                 │
│   Old gen                                   │
├─────────────────────────────────────────────┤
│  Metaspace (off-heap, per ClassLoader)      │
│   Class metadata, method bytecode, vtables  │
├──────────────┬──────────────────────────────┤
│  Stack T1    │  Stack T2   │  Stack T3 ...  │
│  (frames)    │  (frames)   │  (frames)      │
├──────────────┴─────────────┴────────────────┤
│  PC Register (per thread)                   │
│  Native Method Stack (per thread)           │
└─────────────────────────────────────────────┘

QA relevance: When a long-running automation suite crashes with OutOfMemoryError, knowing which area is exhausted tells you where to look:

  • Heap OOM → large test data, retained WebDriver instances, static collections
  • Metaspace OOM → excessive dynamic proxy / reflection class generation
  • StackOverflow → recursive page object or helper calls

// WHAT INTERVIEWERS LOOK FOR

The distinction between heap (shared, GC'd) and stack (per-thread, automatic). The PermGen → Metaspace migration story. Ability to map an OOM error message to the correct memory area. Senior candidates mention Code Cache and the JIT.

// COMMON PITFALL

Conflating metaspace with heap. Metaspace is off-heap native memory — it's not collected by the normal GC cycle and doesn't shrink automatically. Setting only -Xmx without -XX:MaxMetaspaceSize leaves metaspace unbounded.