BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ JVM and performance

Java language

JVM memory: heap, stack and limits

Objects live on the heap, shared by all threads and cleaned by the garbage collector.

๐Ÿ”Ž Unravel this example

At a glance

Mental model

The heap is a big warehouse shared by the whole company, with cleaners who throw away boxes nobody refers to.

What happens, in order
  1. 1new Order() allocates on the heap; the variable order (a reference) is on the stackPrimitives in locals sit on the stack; objects and arrays and their fields live on the heap.
  2. 2Size options: -Xms initial heap, -Xmx maximum heap, -Xss thread stack size, -XX:MaxMetaspaceSize for class metadataIn containers, set the limit relative to the container memory (-XX:MaxRAMPercentage=75).
  3. 3Runtime.getRuntime().maxMemory(), totalMemory() and freeMemory() show the current numbers; ManagementFactory.getMemoryMXBean() gives detailed usage
  4. 4The heap has a young generation (new objects, collected often and cheaply) and an old generation (survivors, collected rarely); metaspace holds class definitions outside the heap
Remember
Watch out
Raising -Xmx to hide a leakSetting -Xmx above the container limit, so the OS kills the processIgnoring non-heap memoryCatching OutOfMemoryError and continuing
Example (highlighted lines explain it)
public class Mem {  static String report() {    Runtime rt = Runtime.getRuntime();    long used = rt.totalMemory() - rt.freeMemory();    return "used " + used / 1_048_576 + " MB of max " + rt.maxMemory() / 1_048_576 + " MB on " + rt.availableProcessors() + " cores";  }  static int depth(int n) { return depth(n + 1); }  static boolean overflows() {    try { depth(0); return false; } catch (StackOverflowError e) { return true; }  }}
  1. line 4 uses totalMemory, the core of JVM memory: heap, stack and limits
  2. line 5 uses maxMemory, the core of JVM memory: heap, stack and limits
  3. line 9 uses StackOverflowError, the core of JVM memory: heap, stack and limits
Read the full explanation (about 2 min)

Objects live on the heap, shared by all threads and cleaned by the garbage collector. Each thread also has a small stack for method calls and local variables. Running out of either gives OutOfMemoryError or StackOverflowError.

A mental model

The heap is a big warehouse shared by the whole company, with cleaners who throw away boxes nobody refers to. A stack is each worker's small desk holding the papers for the job in hand, stacked in order and cleared as each job finishes.

How it works

new Order() allocates on the heap; the variable order (a reference) is on the stack. Primitives in locals sit on the stack; objects and arrays and their fields live on the heap.

Size options: -Xms initial heap, -Xmx maximum heap, -Xss thread stack size, -XX:MaxMetaspaceSize for class metadata. In containers, set the limit relative to the container memory (-XX:MaxRAMPercentage=75).

Runtime.getRuntime().maxMemory(), totalMemory() and freeMemory() show the current numbers; ManagementFactory.getMemoryMXBean() gives detailed usage.

The heap has a young generation (new objects, collected often and cheaply) and an old generation (survivors, collected rarely); metaspace holds class definitions outside the heap.

Going deeper

OutOfMemoryError: Java heap space usually means a leak or an unbounded collection, not a too-small heap: take a heap dump (-XX:+HeapDumpOnOutOfMemoryError) and look at what dominates. Other variants: Metaspace (class loader leak), unable to create native thread (too many threads or the OS limit), GC overhead limit exceeded.

StackOverflowError comes from endless or very deep recursion; each frame costs some hundred bytes, and the default stack is typically 512 KB to 1 MB. Fix the base case rather than raising -Xss.

Memory seen by the OS (RSS) is more than the heap: it also contains metaspace, thread stacks, code cache, direct buffers and GC structures.

Under the hood

Allocation in the young generation is a pointer bump inside a per-thread allocation buffer (TLAB), which is why creating short-lived objects is cheap. A thread's stack frames hold local variables, the operand stack and a return address.

Common mistakes

  • Raising -Xmx to hide a leak.
  • Setting -Xmx above the container limit, so the OS kills the process.
  • Ignoring non-heap memory.
  • Catching OutOfMemoryError and continuing.

How Unravel recognises it

When you paste code, Unravel looks for these signs of jvm memory: heap, stack and limits. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is JVM memory: heap, stack and limits?

Objects live on the heap, shared by all threads and cleaned by the garbage collector. Each thread also has a small stack for method calls and local variables. Running out of either gives OutOfMemoryError or StackOverflowError.

What are the most common mistakes with JVM memory: heap, stack and limits?

Raising -Xmx to hide a leak. Setting -Xmx above the container limit, so the OS kills the process. Ignoring non-heap memory. Catching OutOfMemoryError and continuing.

How can I see JVM memory: heap, stack and limits in real code?

Paste your own Java into Unravel and it will point out where jvm memory: heap, stack and limits appears, explain how it works at the detail level you choose, and draw the flow of the code around it.