Heap tuning configures how much memory the JVM allocates for object storage and how it is divided between generations. Proper sizing prevents OutOfMemoryError and minimizes GC pauses.

Heap Structure

  ┌─────────────────────────────────────────┐
│                 Heap                     │
│  ┌──────────────┬─────────────────────┐ │
│  │ Young Gen    │     Old Gen         │ │
│  │ Eden|S0|S1   │                     │ │
│  └──────────────┴─────────────────────┘ │
└─────────────────────────────────────────┘
         + Metaspace (off-heap, class metadata)
         + Thread stacks, code cache, direct memory
  

Key JVM Flags

  # Fixed heap size (recommended for production)
-Xms4g -Xmx4g

# Young generation size
-Xmn1g
# or ratio: -XX:NewRatio=2  (Old:Young = 2:1)

# Metaspace (replaces PermGen since Java 8)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m

# Stack size per thread
-Xss1m

# Direct memory (NIO buffers)
-XX:MaxDirectMemorySize=512m
  

Sizing Guidelines

Application type Heap size Notes
Small REST API 512m–1g Low object allocation
Medium web app 2g–4g Moderate caching
Data processing 8g–32g Large in-memory datasets
Microservice 256m–512m Many small JVMs

Rule of thumb: Set -Xms equal to -Xmx to avoid heap resize pauses at startup.

Container-Aware Settings

  # Respect container memory limits (Java 10+)
-XX:MaxRAMPercentage=75.0
-XX:InitialRAMPercentage=75.0

# Exit on OOM (let orchestrator restart)
-XX:+ExitOnOutOfMemoryError
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/heapdump.hprof
  

OutOfMemoryError Types

Error Cause Fix
Java heap space Objects exceed heap Increase -Xmx, fix memory leak
Metaspace Too many classes loaded Increase metaspace, check class loaders
Unable to create native thread Too many threads Reduce threads, increase -Xss or ulimit
Direct buffer memory NIO buffers exhausted Increase MaxDirectMemorySize
GC overhead limit exceeded GC spends >98% time, frees <2% Increase heap or fix leak

Analyzing Heap Dumps

  # Generate heap dump
jcmd <pid> GC.heap_dump /tmp/heap.hprof

# Or on OOM (automatic)
-XX:+HeapDumpOnOutOfMemoryError

# Analyze with Eclipse MAT or VisualVM
jhat /tmp/heap.hprof  # basic HTML report
  

Look for:

  • Leak suspects — objects retaining unexpected memory
  • Duplicate strings — inefficient string storage
  • Large collections — unbounded caches or lists

Monitoring Heap Usage

  # Live heap summary
jcmd <pid> GC.heap_info

# JVM stats
jstat -gc <pid> 1000 10   # GC stats every 1s, 10 times

# Via Actuator (Spring Boot)
GET /actuator/metrics/jvm.memory.used
GET /actuator/metrics/jvm.memory.max
  

Best Practices

  • Always set -Xms = -Xmx in production
  • Use MaxRAMPercentage in containers instead of fixed sizes
  • Enable heap dump on OOM for post-mortem analysis
  • Profile before tuning — don’t guess heap sizes
  • Monitor GC logs alongside heap metrics