Sun JVM 6 Memory Diagnosis and Tuning
Main Command Line Options
option | default | description |
-server | -client | server mode |
-XX:+UseParallelGC | Y on server | use parallel GC for new gen |
-XX:ParallelGCThreads | number of processor(s) | number of parallel GC threads |
-XX:+UseParallelOldGC | | |
-XX:+AggressiveOpts | on | |
-Xss | | thread stack size |
-Xms | 1/64 of physical mem | initial heap size |
-Xmx | min{1/4 of physical mem, 1GB} | max heap size |
-Xmn (-XX:NewSize) | | initial new size (aka young generation). 1/4 of heap is suggested. |
-XX:MaxNewSize | | max new size |
-XX:PermSize | | initial permanent size |
-XX:MaxPermSize | 64M | max permanent size |
-verbose:gc (-Xloggc:path/to/logfile) | | output GC to log file |
-XX:+PrintGCTimeStamps | | output timestamp to GC log |
-XX:+PrintGCDetails | | detailed GC log |
-XX:PrintClassHistogram | | output heap stat info when getting SIGQUIT (by kill -3 <pid>) |
-XX:+HeapDumpOnOutOfMemoryError | | output heap dump when OutOfMemoryError happens |
-XX:SurvivorRatio | | ratio of eden space size to S0 & S1 size |
-XX:MaxTenuringThreshold | | |
-XX:TargetSurvivorRatio | 50 | percentage of the survivor spaces to be occupied |
Usage
Check memory leak
-verbose:gc -Xloggc:mem.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
Check heap
jstat -gcutil -h10 <pid> 5000
Heap stat info
-verbose:gc -Xloggc:mem.log -XX:+PrintClassHistogram
then
kill -3 <pid>
or
jmap -histo <pid>
Heap dump
Wait for OutOfMemoryError with following options:
-XX:+HeapDumpOnOutOfMemoryError
kill process (with -3 option) with following options:
-XX:+HeapDumpOnCtrlBreak
or
jmap -dump:format=b,file=filename <pid>
Useful Tools
Experienced Issues
I made a system containing Drools rule engine that consumes a lot of memory. Although a lot of memory is allocated for its heap, it still crashed one day for lack of Permanent Generation space with an exception of "java.lang.OutOfMemoryError: PermGen space".
In Sun JVM's garbage collection design, there are three generations of objects: Young, Tenured and Permanent. By default, the third one is 64MB in JVM 6.
Many third-party libs like XML parser can consume a lot of memory in PermGen such as cached strings. In this example, there are more than 1000 rules, so eventually the PermGen space was used out. The solution was to allocate more for it (usually 128MB is enough. Here I allocated 256MB):
java -server -Xmn2000M -Xms6000M -Xmx10000M -XX:SurvivorRatio=8 -XX:MaxPermSize=256M -verbose:gc \
-XX:+PrintClassHistogram -XX:+PrintGCDetails -Xloggc:$currDir/log/mem.log <class>