Under The Hood
backend java Java 8+ (G1 GC), Java 21 (generational G1)

JVM memory: stack vs heap

Last updated
Prerequisites:
Java method and object basics
Familiarity with references and primitives
  • java
  • jvm
  • memory
  • stack
  • heap
  • garbage-collection

Read at your depth

The practical view

Each thread has its own stack holding method frames: local variables, primitive values, and object references live here; the objects themselves live on the heap. When a method returns, its frame is popped and its locals are gone. The heap is shared by all threads and holds all objects and arrays; the garbage collector reclaims objects no longer reachable from GC roots (static fields, stack frames, JNI references). new always allocates on the heap (though escape analysis can place small objects on the stack). StackOverflowError comes from unbounded recursion (frames exceed stack size); OutOfMemoryError: Java heap space from exhausting the heap.

Legacy vs modern

Allocation that escapes vs allocation eliminated by escape analysis

Objects that escape to the heap drive GC pressure; the JIT can stack-allocate or scalar-replace non-escaping objects, eliminating the allocation entirely.

before → after
Escaping object
long sum = 0;
for (int i = 0; i < N; i++) {
  Point p = new Point(i, i);   // escapes? if returned/stored, heap  // ❌ OLD: new Point() per iteration → Eden alloc + GC pressure
  sum += p.distance();
}
Scalar-replaced (JIT-optimized) equivalent
// Same loop after escape analysis: fields promoted to locals.
double total = 0;
for (int i = 0; i < N; i++) {
  int px = i, py = i;          // scalar replacement  // ✅ NEW: scalar replacement → fields in registers, no object
  total += Math.hypot(px, py); // no object exists at all
}

Interview gotchas

Context

The interviewer wants to separate memorized claims ('stack is fast') from the actual mechanisms (pointer bump, frame pop, escape analysis).

The mechanical answer

Stack allocation is a pointer bump in the current frame and deallocation is a frame pop — no locking, no bookkeeping, no GC interaction, and excellent cache locality because the frame is hot. The JVM does not allocate Java objects on the stack in the classic sense, but escape analysis in C2 lets it eliminate allocations entirely: if an object never escapes the method (not stored in a field, not returned, not passed to a call the JIT can see), its fields are scalar-replaced into registers and stack slots. So the 'stack allocation' win is really allocation elimination plus the frame's natural locality.

Trap

The trap answer is 'the JVM puts objects on the stack when they are small'. Escape analysis does not look at size — it looks at the object's lifetime relative to the method (escape state: NoEscape/ArgEscape/GlobalEscape). Also, some candidates claim all allocations go through malloc — HotSpot's TLAB bump allocation bypasses the allocator entirely. Mentioning TLABs and scalar replacement is what makes the answer senior-level.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.