Troubleshooting

Reference video (Chinese)

Causes of OutOfMemoryError

  1. Allocating too many objects at once → use pagination/streaming
  2. Memory leak: reachable but no-longer-needed objects still retained → find and release them
  3. 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%

Reference (Chinese)

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:

  1. Loading many large objects at once (e.g., unpaged SQL query). If young gen can’t hold them, they quickly promote to old.
  2. 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

  1. 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.
  2. Use jstat to check GC counts and total time.