Fundamentals 38 min read

Mastering JVM Memory: From Heap Layout to Garbage Collection Tuning

This article provides a comprehensive guide to JVM internals, covering runtime data areas, heap segmentation, object allocation, reference types, class loading phases, garbage collection algorithms, collector choices across JDK versions, performance tuning commands, and practical troubleshooting techniques for production Java applications.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Mastering JVM Memory: From Heap Layout to Garbage Collection Tuning

JVM Memory Layout

The JVM runtime data area consists of the heap, method area (Metaspace in JDK 8+), virtual machine stack, native method stack, and program counter.

Heap Details

The heap stores object instances and arrays, is shared among threads, and is the primary region for garbage collection. It is divided into young and old generations; the young generation further contains Eden, Survivor 1, and Survivor 2 spaces.

Method (Metaspace) Area

Stores class metadata, constants, and static variables. Since JDK 8 the term "method area" is replaced by Metaspace. Excessive class loading (e.g., by frameworks like Spring) can cause Metaspace overflow.

Virtual Machine Stack

Thread‑private stack holding stack frames, each containing a local variable table, operand stack, dynamic linking information, and return address. StackOverflowError occurs when the stack depth exceeds limits; OutOfMemoryError occurs when the stack cannot be expanded.

Local Variable Table : Stores method parameters and local variables.

Operand Stack : Records push/pop operations of bytecode instructions.

Dynamic Linking : Resolves symbolic references to direct references at runtime.

Return Address : Points to the next bytecode instruction after method return.

Native Method Stack

Similar to the VM stack but serves native methods; in HotSpot it is merged with the VM stack and also throws StackOverflowError and OutOfMemoryError.

Program Counter (PC)

Thread‑private pointer to the next instruction to execute.

Object Allocation Strategy

Objects are allocated in Eden; if Eden lacks space, a Minor GC is triggered. Surviving objects move to Survivor spaces; after reaching a certain age (default 15) they are promoted to the old generation. Large objects are allocated directly in the old generation to avoid copying overhead.

Object Creation Steps

Class loading check

Memory allocation (pointer bumping or free‑list)

Zero‑value initialization

Object header setup (class pointer, hash, GC age, lock flags)

Execution of the init method

Object Reference Types

Strong Reference : Default reference type.

Soft Reference : Collected only when memory is low.

Weak Reference : Collected on any GC cycle.

Phantom Reference : Used to track object finalization.

JVM Class Loading Process

The phases are loading, verification, preparation, resolution, and initialization.

Loading Phase

Read the binary byte stream of the class.

Convert the byte stream into a runtime data structure in the method area.

Create a java.lang.Class object in the heap.

Verification Phase

File format verification

Metadata verification

Bytecode verification

Symbolic reference verification

Preparation Phase

Allocate memory for static variables and set them to default values.

Resolution Phase

Replace symbolic references in the constant pool with direct references.

Initialization Phase

Execute the class’s static initializers and <clinit> method.

Class Loader Mechanisms

Java uses the parent‑delegation model: a class loader first delegates loading to its parent before attempting to load the class itself. This ensures core classes are loaded first and prevents duplicate loading.

Breaking the delegation (e.g., custom class loaders, Tomcat’s WebAppClassLoader) can lead to multiple versions of the same class and potential conflicts.

Tomcat Class Loading

Check local cache for the class.

If not found, check the system class loader cache.

Attempt loading with ExtClassLoader (bypassing AppClassLoader).

If still not found, use BootstrapClassLoader.

Finally, fall back to AppClassLoader or throw an exception.

This deliberately breaks the parent‑delegation model to prioritize web‑app classes.

JVM Garbage Collection

Reference Counting (Deprecated)

Simple but cannot handle cyclic references.

Reachability Analysis

Starts from GC roots (threads, static fields, JNI refs) and marks reachable objects; unreachable objects are reclaimed.

Mark‑Sweep, Mark‑Compact, and Generational Collection

Copying algorithm (young generation)

Mark‑Sweep (CMS, old generation)

Mark‑Compact (Serial Old, Parallel Old)

Generational collection selects algorithms based on object age.

Garbage Collectors by JDK Version

JDK 3 : Serial (single‑threaded), ParNew (multithreaded copy collector).

JDK 5 : Parallel Scavenge (throughput‑oriented), Serial Old.

JDK 8 : CMS (low‑pause concurrent collector), Parallel Old.

JDK 9 : G1 (predictable pause times, region‑based).

JDK 11 : ZGC (concurrent, low‑pause, supports up to TB‑scale heaps).

JDK 12 : Shenandoah (pause‑independent).

JDK 13‑14 : ZGC expanded to macOS/Windows, CMS removed.

GC Configuration Tips

Set heap size limits (e.g., 2/3 of system memory).

Adjust young/old generation ratios based on workload.

Use tools like GCeasy to analyze GC logs.

JVM Performance Tuning Commands

jps

– List Java processes. jinfo – Show JVM flags. jstat – Monitor GC and memory statistics. jstack – Thread dump (detect deadlocks, long‑running threads). jmap – Heap dump and histogram. jhsdb – Advanced debugging (heap, core files).

JDK New Features

JDK 8: Lambda expressions, Stream API, HashMap improvements.

JDK 9: Default G1 collector, enhanced Stream API.

JDK 10: Parallel full GC improvements.

JDK 11: ZGC with sub‑millisecond pauses.

JDK 12: Shenandoah GC.

JDK 13: Larger heap support for ZGC.

JDK 14: Removal of CMS, deprecation of ParallelScavenge+SerialOld combo.

Online Fault Diagnosis

Typical steps: isolate the faulty instance, preserve the state, then investigate.

Network: ss -antp Network stats: netstat -s Process resources: lsof -p $PID CPU: mpstat, vmstat, sar -p ALL I/O: iostat -x Memory: free -h Global info: ps -ef, dmesg, sysctl -a Heap dump: jmap -dump:format=b,file=heap.bin $PID Thread dump: jstack $PID Core dump:

gcore -o core $PID

Common Issues and Solutions

Memory leaks from unbounded caches – replace with Guava Cache using weak references.

File‑handle leaks – ensure streams are closed in finally blocks.

High CPU due to GC – analyze object age distribution, tune MaxTenuringThreshold, enable ParallelRefProcEnabled, consider G1 with pause target.

Swap usage causing long GC pauses – disable swap on production servers.

By applying these tuning steps and monitoring practices, JVM performance can be stabilized even under heavy load.

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.

JVMMemory ManagementGarbage Collectionperformance tuning
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology innovations.

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.