工具:
- jstat
- jmap
- jhat
1.jstat查看gc情況
S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used) EC、EU:Eden區容量和使用量 OC、OU:年老代容量和使用量 PC、PU:永久代容量和使用量 YGC、YGT:年輕代GC次數和GC耗時 FGC、FGCT:Full GC次數和Full GC耗時 GCT:GC總耗時
這次遇到的情況是,old區到了指定的回收閥值觸發fgc,但old區回收不了,持續增長(但一直頻繁fgc)。
jvm配置如下:
-server -XX:PermSize=64m -XX:MaxPermSize=128m -Xmn500m -Xms3000m -Xmx3000m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/apps/oom/gc.hprof -XX:ErrorFile=/var/log/java_error_%p.log
2.當發現old區回收不了的時候,使用jmap分析內存情況。
jmap -heap pid
使用jmap -heap pid查看進程堆內存使用情況,包括使用的GC算法、堆配置參數和各代中堆內存使用情況。
例如:
Attaching to process ID 10253, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.65-b04 using parallel threads in the new generation. using thread-local object allocation. Concurrent Mark-Sweep GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 3145728000 (3000.0MB) NewSize = 524288000 (500.0MB) MaxNewSize = 524288000 (500.0MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 67108864 (64.0MB) MaxPermSize = 134217728 (128.0MB) G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 471859200 (450.0MB) used = 113244456 (107.99832916259766MB) free = 358614744 (342.00167083740234MB) 23.99962870279948% used Eden Space: capacity = 419430400 (400.0MB) used = 66465208 (63.38616180419922MB) free = 352965192 (336.6138381958008MB) 15.846540451049805% used From Space: capacity = 52428800 (50.0MB) used = 46779248 (44.61216735839844MB) free = 5649552 (5.3878326416015625MB) 89.22433471679688% used To Space: capacity = 52428800 (50.0MB) used = 0 (0.0MB) free = 52428800 (50.0MB) 0.0% used concurrent mark-sweep generation: capacity = 2621440000 (2500.0MB) used = 259229192 (247.22022247314453MB) free = 2362210808 (2252.7797775268555MB) 9.888808898925781% used Perm Generation: capacity = 67108864 (64.0MB) used = 37059440 (35.34263610839844MB) free = 30049424 (28.657363891601562MB) 55.22286891937256% used 19254 interned Strings occupying 2351584 bytes.
jmap -heap 只能查看jvm各個區的詳細使用情況,內存中到底有哪些數據(咬着old區不放)得用jmap -histo進行分析。
jmap -histo[:live] pid
例如:
num #instances #bytes class name ---------------------------------------------- 1: 32727 88492856 [I 2: 369677 62058808 [C 3: 145200 54408968 [B 4: 545638 17460416 java.util.HashMap$Entry 5: 451316 14442112 org.wltea.analyzer.dic.DictSegment 6: 158024 10051408 [Ljava.lang.Object; 7: 59193 8940656 <constMethodKlass> 8: 59193 7588736 <methodKlass> 9: 6105 7139824 <constantPoolKlass> 10: 39329 6230272 [Ljava.util.HashMap$Entry; 11: 255466 6131184 java.lang.String 12: 182746 5847872 [Lorg.wltea.analyzer.dic.DictSegment; 13: 6097 4220448 <instanceKlassKlass> 14: 5064 3900032 <constantPoolCacheKlass> 15: 100084 3202688 org.apache.lucene.document.LazyDocument$LazyField 16: 78719 3148760 java.util.LinkedHashMap$Entry 17: 11980 3120656 [S 18: 122352 2936448 java.util.ArrayList 19: 9747 2740192 [J 20: 95649 2295576 java.util.LinkedList$Node 21: 53484 2139360 org.apache.lucene.document.FieldType 22: 125687 2010992 java.lang.Character 23: 41021 1969008 org.apache.lucene.analysis.tokenattributes.PackedTokenAttributeImpl 24: 53663 1913576 [Lorg.apache.lucene.util.automaton.Transition;
class name是對象類型,說明如下:
B byte C char D double F float I int J long Z boolean [ 數組,如[I表示int[] [L+類名 其他對象
如果還需要看更加詳細的信息,則使用:
jmap -dump:format=b,file=dumpFileName pid
dump出來的文件可以用MAT、VisualVM等工具查看,也可以使用jhat。
jhat -port 9999 dumpFileName
如果dump出來的文件過大,可能需要指定Xmx(jhat實際啟動了一個web應用)。
jhat -J-Xmx1000m -port 9999 dumpFileName
啟動成功后,則可以通過瀏覽器查看:
ip:port
例如:

在該頁面的最后面有一些查詢工具,例如:OQL(object query language)

例如上圖查詢的是長度大於256的int數組。
------------------------------------
企業開發的時候,有可能碰到的問題:
- oom
- 內存泄露
- 線程死鎖
- 鎖爭用
- java進程消耗cpu過高
工具:
- jps(java virtual machine process status tool)
jps主要用來輸出JVM中運行的進程狀態信息。語法格式如下:
jps [options] [hostid]
q 不輸出類名、Jar名和傳入main方法的參數 -m 輸出傳入main方法的參數 -l 輸出main類或Jar的全限名 -v 輸出傳入JVM的參數
- jstack
jstack主要用來查看某個Java進程內的線程堆棧信息。
檢查過程:
1)得到相應的進程號(ps -ef |grep ***)
2)查詢該進程對應的線程信息(top -Hp pid)

這里的Pid需要轉成16進制,后面需要用到。
[apps@java1818 bin]$ printf "%x\n" 10831 2a4f
使用jstack進行分析
[apps@java1818 bin]$ jstack 10253 | grep 2a4f "http-bio-2223-exec-172" daemon prio=10 tid=0x00007fb2d400a000 nid=0x2a4f waiting on condition [0x00007fb28c5c4000]
也可以將信息dump到文件中進行分析,更加方便。
- jmap ( memory map ) / jhat ( java heap analysis tool )
jmap用來查看堆內存使用狀況,一般結合jhat使用。
jmap -heap pid jmap -histo[:live] pid jmap -dump:format=b,file=dumpFileName pid
- jstat

堆內存 = 年輕代 + 年老代 + 永久代 年輕代 = Eden區 + 兩個Survivor區(From和To)
- hprof ( heap/cpu profiling tool )
hprof能夠展現CPU使用率,統計堆內存使用情況。
參考資料:
http://my.oschina.net/feichexia/blog/196575
