Troubleshooting
Causes of OutOfMemoryError
- Allocating too many objects at once → use pagination/streaming
- Memory leak: reachable but no-longer-needed objects still retained → find and release them
- Insufficient resources → use to inspect the heap
jmap is a JDK CLI tool to generate a heap dump. A heap dump is a binary snapshot of all objects on the heap. Or add -XX:+HeapDumpOnOutOfMemoryError so the JVM dumps the heap automatically on OOM.
Common Leak Sources
Heap Dump
Add -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/ruoke/Documents/java_web This generates a heap dump to analyze with jvisualvm. Find GC Roots, then locate the code line from the error stack.
Useful JVM Options
Heap
Initial heap (-Xms): -Xms4G
Max heap (-Xmx): -Xmx4G
Usually set them equal to avoid expansion overhead.
-Xmn512m: allocate 256MB to young gen
A larger young gen keeps objects young longer; minor GCs are cheaper than full GCs.
-XX:NewRatio=1
Sets old:young ratio to 1.
-XX:MaxMetaspaceSize=2G
Max Metaspace size.
GC
-XX:+UseConcMarkSweepGC
Use CMS collector.
-XX:MaxGCPauseMillis=50
With G1, set desired max pause to 50ms.
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
Print GC logs with timestamps.
-Xloggc:/path/to/gc.log
Write GC logs to file.
CPU 100%
Insufficient Memory
When physical RAM is low, the OS uses Swap (virtual memory) on disk. Long-idle processes may be paged out so RAM is freed for others.
Frequent GC
A too-small young gen or creating many short-lived objects can cause frequent minor GCs.
Frequent full GCs are serious.
jstat -gc 12345 1000 5
Monitor the Java process with PID 12345; print GC info every 1s for 5 times.
OC/OU are old-gen capacity/usage.
Full GC causes include:
- Loading many large objects at once (e.g., unpaged SQL query). If young gen can’t hold them, they quickly promote to old.
- Memory leaks: unclosed file/db/network resources; static collections (static List/Map) live as long as the JVM and can retain objects; forgetting threadLocal.remove().
jmap -histo pid | head -n20
List live objects on the heap ranked by retained size.
Lock Contention
Business Logic Issues
Infinite loops/deadlocks/unbounded recursion
Investigation Steps
- Use top to find the hottest process; ps -Lfp PID to find the hottest thread; convert TID to hex. Generate a thread dump with jstack for that Java process and search for the hex TID to see the stack trace and pinpoint code lines.
- Use jstat to check GC counts and total time.