What's Actually Happening
Java applications run out of heap memory. OutOfMemoryError is thrown, applications crash, or garbage collection causes performance issues.
The Error You'll See
OutOfMemoryError Java heap space:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.util.Arrays.copyOf(Arrays.java:3332)OutOfMemoryError GC overhead:
java.lang.OutOfMemoryError: GC overhead limit exceededMemory warning:
```bash tail -f /var/log/app.log
WARNING: java.lang.OutOfMemoryError: Java heap space ```
Why This Happens
- 1.Heap too small - Initial heap size insufficient
- 2.Memory leak - Objects not being garbage collected
- 3.Large data processing - Processing data larger than heap
- 4.Too many objects - Creating too many objects
- 5.GC tuning needed - Garbage collection not optimized
- 6.Off-heap memory - Not enough native memory
- 7.Memory fragmentation - Heap fragmentation
Step 1: Check Current Heap Settings
```bash ps aux | grep java
# Look for -Xmx and -Xms flags
# Check JVM arguments: jcmd <pid> VM.flags
# Get heap usage: jcmd <pid> GC.heap_info
# Check memory: jmap -heap <pid> ```
Step 2: Increase Heap Size
```bash # Set initial and max heap: java -Xms512m -Xmx2g MyApp
# Or in environment: export JAVA_OPTS="-Xms512m -Xmx2g"
# Common settings: # Small: -Xms256m -Xmx512m # Medium: -Xms512m -Xmx2g # Large: -Xms2g -Xmx4g
# As fraction of system memory: # Leave ~25% for OS and other processes ```
Step 3: Check for Memory Leaks
```bash # Generate heap dump: jcmd <pid> GC.heap_dump /tmp/heap.hprof
# Or use jmap: jmap -dump:format=b,file=/tmp/heap.hprof <pid>
# Analyze with tools: # - Eclipse MAT # - VisualVM # - YourKit # - JProfiler
# Check live objects: jcmd <pid> GC.class_histogram | head -20 ```
Step 4: Monitor Memory Usage
```bash # JConsole: jconsole <pid>
# VisualVM: jvisualvm
# Command line: jstat -gc <pid> 1000
# Memory pools: jcmd <pid> VM.info | grep -A 20 "Memory" ```
Step 5: Analyze GC Logs
```bash # Enable GC logging: -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/gc.log
# Modern Java (11+): -Xlog:gc*:file=/var/log/gc.log
# Check GC logs: tail -f /var/log/gc.log
# Analyze with: # - GCViewer # - GCEasy.io ```
Step 6: Tune Garbage Collection
```bash # Use G1GC (Java 11+ default): -XX:+UseG1GC
# Set max GC pause: -XX:MaxGCPauseMillis=200
# For throughput: -XX:+UseParallelGC
# For low latency: -XX:+UseZGC
# Common settings: -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 ```
Step 7: Check Metaspace
```bash # Metaspace is for class metadata # If OutOfMemoryError: Metaspace
# Increase metaspace: -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# Check metaspace usage: jcmd <pid> GC.heap_info | grep Metaspace
# Enable class unloading: -XX:+CMSClassUnloadingEnabled ```
Step 8: Handle Large Objects
```bash # For large data: # Process in chunks # Use streaming APIs # Avoid loading all data into memory
# Use off-heap memory: -XX:MaxDirectMemorySize=1g
# For large files: # Use streaming I/O # Use memory-mapped files ```
Step 9: Container Memory Limits
```bash # In Docker/container: # Set JVM heap based on container limit
# Java 10+ automatically detects container limits # For older versions: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
# Or set explicitly: java -Xmx$(echo $(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) * 0.75 | bc) MyApp
# In Kubernetes: # Set JVM heap based on container limit env: - name: JAVA_OPTS value: "-Xms512m -Xmx768m" ```
Step 10: Monitor and Alert
```bash # JMX monitoring: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
# Prometheus JMX exporter: java -javaagent:jmx_prometheus_javaagent.jar=8080:config.yaml -jar app.jar
# Key metrics: # - jvm_memory_used_bytes # - jvm_gc_collection_seconds # - jvm_threads_current ```
Java Heap Space Error Checklist
| Check | Command | Expected |
|---|---|---|
| Heap size | ps aux grep | -Xmx set |
| Memory usage | jcmd GC.heap_info | Within limits |
| GC logs | tail gc.log | No excessive GC |
| Heap dump | jcmd heap_dump | Analyze for leaks |
| Metaspace | jcmd GC.heap_info | Sufficient |
| Container limit | /sys/fs/cgroup | JVM fits |
Verify the Fix
```bash jcmd <pid> VM.flags | grep -E "Xmx|Xms"
jcmd <pid> GC.heap_info
jstat -gc <pid> 1000 5
tail -f /var/log/gc.log
jcmd <pid> GC.class_histogram | head -10
ps aux | grep java ```
Related Issues
- [Fix Java OutOfMemoryError](/articles/fix-java-outofmemoryerror)
- [Fix Java Application Crash](/articles/fix-java-application-crash)
- [Fix Docker Out of Memory](/articles/fix-docker-out-of-memory)