Fundamentals 19 min read

Master JVM Memory: Heap, Metaspace, Stack, PC & Direct Memory Explained

This article provides a comprehensive overview of the Java Virtual Machine memory layout, covering the heap, metaspace, stack frames, program counter, direct memory, and code cache, along with practical tuning tips, demonstration code for heap OOM, and references for deeper study.

Java Interview Crash Guide
Java Interview Crash Guide
Java Interview Crash Guide
Master JVM Memory: Heap, Metaspace, Stack, PC & Direct Memory Explained

This JVM series summarizes key knowledge points to help readers quickly grasp JVM memory concepts; for a systematic study, refer to professional books and documentation.

JVM memory area overview

Heap allocation and OOM demonstration

How a new object is allocated

Method area to Metaspace transition

What is a stack frame and how to understand it

Native method stack

Program counter

Code Cache

Memory is a critical system resource that bridges the disk and CPU, carrying the operating system and applications. The JVM memory layout defines how Java allocates, manages, and releases memory to ensure efficient and stable execution.

JVM memory layout diagram
JVM memory layout diagram

1. Heap (堆区)

The heap is the primary area where OutOfMemoryError (OOM) occurs. It is the largest memory region, shared by all threads, storing almost all object instances and arrays. With JIT optimizations like escape analysis, some objects may be allocated on the stack, reducing heap pressure.

Extended topic: JIT compilation optimization – escape analysis. Recommended reading: Deep dive into Java escape analysis (https://www.hollischuang.com/archives/2583)

In Java 8, the heap is managed by the garbage collector and is divided into Young and Old generations. The Young generation includes Eden, Survivor (S0, S1) spaces, and may use Thread‑Local Allocation Buffers (TLAB) for faster allocation.

2. Heap Adjustment

The heap can be physically non‑contiguous as long as it appears contiguous logically. It can be fixed‑size or dynamically resized at runtime.

How to adjust?

Use JVM parameters such as -Xms256M -Xmx1024M where -Xms sets the initial heap size and -Xmx sets the maximum heap size.

In production, it is common to set -Xms and -Xmx to the same value to avoid heap expansion overhead during GC.

3. Default Heap Allocation

The default sizes depend on the ratio parameters. For example, with InitialSurvivorRatio=8 and NewRatio=2, if Eden is 40 MB, each Survivor space is 5 MB, the Young generation totals 50 MB, and the Old generation is 100 MB, giving a total heap of 150 MB.

Check the defaults with: java -XX:+PrintFlagsFinal -version Relevant output includes flags like InitialSurvivorRatio and NewRatio.

4. Heap OOM Demonstration

/**
 * VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
 */
public class HeapOOMTest {
    public static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        List<byte[]> byteList = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            byte[] bytes = new byte[2 * _1MB];
            byteList.add(bytes);
        }
    }
}

Running the program produces:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid32372.hprof ...
Heap dump file created [7774077 bytes in 0.009 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at jvm.HeapOOMTest.main(HeapOOMTest.java:18)

The flag -XX:+HeapDumpOnOutOfMemoryError triggers a heap dump when OOM occurs, which is valuable for diagnosing rare memory issues.

5. Object Allocation Process

When a new object is created, most objects are allocated in Eden. When Eden fills, a Young GC (YGC) occurs, clearing unreachable objects and moving survivors to the Survivor spaces. After several Survivor‑to‑Survivor copies (controlled by -XX:MaxTenuringThreshold, default 15), objects are promoted to the Old generation.

For more on GC concepts, refer to the GC chapter of this series.

6. Metaspace (元空间)

In HotSpot JVM, the former Permanent Generation (method area) stored class metadata. Since Java 8, it has been replaced by Metaspace, which resides in native memory and grows automatically (limited only by the host OS). This eliminates the PermGen OOM problem.

In JDK 8, class metadata is stored in the native heap (Metaspace).

Typical tuning parameters include -XX:MetaspaceSize and -XX:MaxMetaspaceSize.

7. Java Virtual Machine Stack

Each thread gets its own JVM stack, which stores stack frames for Java method execution. A stack frame contains the local variable table, operand stack, dynamic linking information, and return address.

Local Variable Table

Holds method parameters and local variables. Its size is fixed at compile time.

public int test(int a, int b) {
    Object obj = new Object();
    return a + b;
}

Primitive types are stored directly; reference types store a reference to the heap object.

Operand Stack

A LIFO stack used by the execution engine to perform calculations.

public int sum(int a, int b) {
    return a + b;
}

After compilation, the bytecode shows a stack depth of 2 and three local slots.

0: iload_1
1: iload_2
2: iadd
3: ireturn

Dynamic Linking & Return Address

Each frame holds a reference to the constant‑pool entry of the current method for dynamic linking, and the return address for normal or exceptional exits.

8. Native Method Stack

Serves native (non‑Java) method calls. In HotSpot, the native method stack is often merged with the JVM stack. It can also throw StackOverflowError or OutOfMemoryError.

9. Program Counter (PC) Register

A small thread‑local memory that points to the next bytecode instruction to execute. It enables the JVM to resume a thread after a context switch.

10. Direct Memory

Memory allocated outside the Java heap via NIO's DirectByteBuffer. It is not limited by -Xmx but is constrained by the host OS memory.

11. Code Cache

The area where the JVM stores compiled native code (nmethods). The JIT compiler is the main consumer. An OOM in this area appears as java.lang.OutOfMemoryError: CodeCache.

12. Diagnostic Options

Various JVM diagnostic flags can be used to monitor and tune memory areas (e.g., -XX:+PrintGCDetails, -XX:+PrintFlagsFinal).

Diagnostic options
Diagnostic options

References

《深入理解Java虚拟机》 – 周志明

《码出高效》

Metaspace in Java 8

JVM Machine Instruction Diagram

Introduction to JVM Code Cache (https://www.baeldung.com/jvm-code-cache)

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMStackHeapMetaspaceJava memory
Java Interview Crash Guide
Written by

Java Interview Crash Guide

Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.

0 followers
Reader feedback

How this landed with the community

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.