內(nèi)存泄漏是一個比較棘手的問題肪笋,大多數(shù)時候沒有明顯的報錯,這給問題排查帶來很大困難,好在前人已經(jīng)遇到很多類似問題藤乙,也留下了一些典型的排查套路猜揪,大部分時候只需要按圖索驥,一步步來即可坛梁。
套路之工具篇
- ps或者jps
ps:查找活躍的進(jìn)程
典型用法:ps -ef|grep java
jps:查找活躍的 java進(jìn)程*
典型用法:jps -v
- jmap
jmap 可以將java內(nèi)存打印出來而姐,作為內(nèi)存分析工具(如MAT)的輸入 - jinfo
可以用來查看java進(jìn)程的啟動信息,可以看下內(nèi)存堆大小的設(shè)置 - jstat
可以用來打印JVM的運(yùn)行時GC統(tǒng)計信息, 典型用法如
jstat -gcutil 21891 250 2
表示鏈接到21891這個進(jìn)程划咐,每250ms用gcutil打印一次拴念,一共取2個實例,通常打印出來的效果是這樣的
$ jstat -gcutil 19677 1000 2
S0 S1 E O P YGC YGCT FGC FGCT GCT
85.04 0.00 15.15 3.61 44.32 4 0.834 1 0.705 1.538
85.04 0.00 15.15 3.61 44.32 4 0.834 1 0.705 1.538
- MAT
可以分析jmaps生成的內(nèi)存快照褐缠,如果你用Eclipse可以直接在eclipse->help->install software 輸入 http://download.eclipse.org/mat/1.6.1/update-site/ 按照提示安裝
PS:如果命令有任何不清楚政鼠,男人(man)是你的好朋友:)
套路之實戰(zhàn)篇
1. 獲取內(nèi)存dump
進(jìn)程還活著:
- 使用ps查找java進(jìn)程ID
ps -ef|grep java 或者 jps
- jmap 將內(nèi)存dump到本地
jmap -dump:live,format=b,file=dump.bin 19677
會輸出dump.bin文件
已經(jīng)OOM掛了:
提前在java 運(yùn)行參數(shù)添加 -XX:+HeapDumpOnOutOfMemoryError
表示掛了需要dump當(dāng)時內(nèi)存,再添加 -XX:HeapDumpPath=/tmp
表示dump內(nèi)存存放的位置, 這樣當(dāng)應(yīng)用down掉之后队魏,會輸出一個.hprof文件
2. 內(nèi)存分析
- 使用MAT導(dǎo)入上一步生成的dump文件公般,分析之后你會看到類似這樣一張圖
從這里為入口,可以查看哪些對象占用內(nèi)存較大胡桨,內(nèi)存泄漏的可疑點在哪里官帘,比如這個case, 點到Leak Suspects這個鏈接可以看到
這是個比較直觀的問題,HashMapEntry對象占用了超過99%的內(nèi)存空間昧谊,可以直接看業(yè)務(wù)代碼哪里HashMap使用出了問題刽虹。
這是MAT比較簡單的應(yīng)用,其他高級用法可以看MAT官方文檔呢诬,或這篇文章 Java程序內(nèi)存分析:使用mat工具分析內(nèi)存占用 - 孤劍 - 博客園
結(jié)語
相信了解了這些工具與套路涌哲,下次遇到可疑內(nèi)存泄漏或者OOM這樣的嚴(yán)重問題,就不會茫然無措了馅巷。