Fundamentals 12 min read

Understanding JVM Memory Areas: Program Counter, Stack, Heap, and Metaspace

This article provides a comprehensive overview of the Java Virtual Machine's memory layout, detailing the runtime data area—including the program counter, JVM stack, native method stack, heap, and metaspace—while explaining their structures, functions, common errors, and the role of JIT and escape analysis.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding JVM Memory Areas: Program Counter, Stack, Heap, and Metaspace

The article explains how a Java program is compiled into bytecode, loaded by the JVM class loader, and executed using a runtime data area (also called JVM memory) that stores all data needed during execution.

The JVM specification consists of six chapters, covering introduction, JVM structure, compilation, class files, loading/linking/initialization, instruction set, and opcode.

01. Program Counter

The program counter (PC) register is a small, thread‑private memory slot that holds the address of the next bytecode instruction to execute. It enables thread switching, branching, loops, exception handling, and ensures each thread can resume execution correctly. For native methods the PC value is undefined, and the PC never causes an OutOfMemoryError because its size is fixed.

02. Java Virtual Machine Stack

The JVM stack stores a series of stack frames, each corresponding to a method invocation. When a method is called, a new frame is pushed; when it returns, the frame is popped.

Each stack frame contains five parts:

Local Variable Table : stores method parameters and local variables; primitive values are stored directly, object references store the reference.

Operand Stack : used for evaluating expressions and passing arguments between methods.

Reference to Runtime Constant Pool : points to the constant pool of the class that owns the method.

Return Address : records where execution should continue after the method returns.

Dynamic Linking Information : holds a reference to the method’s entry in the runtime constant pool to support dynamic linking.

The JVM stack is also thread‑private and shares the same lifecycle as its thread.

Typical errors related to the stack are:

StackOverflowError – thrown when a thread exceeds the maximum stack depth.

OutOfMemoryError – thrown when the JVM cannot expand the stack due to insufficient native memory.

03. Native Method Stack

The native method stack is similar to the JVM stack but is used for executing native (C/C++) methods. In HotSpot, native and Java stacks are not distinguished.

04. Heap

The heap is a shared memory region created at JVM startup that stores all objects and arrays. Since JDK 7, escape analysis allows some objects to be allocated on the stack when they do not escape the method.

JIT compilation improves performance by translating frequently executed bytecode into native code at runtime. Escape analysis lets the HotSpot VM decide whether an object can be allocated on the stack, reducing heap pressure.

The heap is managed by the garbage collector and is divided into generations: Young Generation (including Eden, From‑Survivor, To‑Survivor) and Old Generation. This division enables more efficient collection.

Common heap‑related OutOfMemoryError cases are:

OutOfMemoryError: GC Overhead Limit Exceeded – the JVM spends too much time in GC and reclaims little heap space.

java.lang.OutOfMemoryError: Java heap space – the heap cannot accommodate a new object allocation.

05. Metaspace

Starting with JDK 8, the permanent generation (PermGen) was removed and replaced by Metaspace, which resides in native memory instead of the JVM heap.

The method area (formerly PermGen) stores class metadata, static variables, and the runtime constant pool. After JDK 8, class metadata lives in Metaspace, while the string constant pool moved to the heap.

Metaspace eliminates the size limitation of the former permanent generation because it uses native memory, and it aligns with the inclusion of JRockit’s memory model in HotSpot.

Understanding these JVM memory regions helps Java developers diagnose memory‑related issues, especially in multithreaded environments, and gives them better control over performance and stability.

Recommended reading links are provided at the end of the original article.

JavaJVMmemory managementHeapRuntime Data Area
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.