天天看點

JVM問題排查步驟 

1、執行jps指令檢視服務程序是否還存在:jps -lv

2、執行top指令檢視CPU和記憶體使用率。若發現有一或多個CPU或記憶體的使用率居高不下(例如80%~100%),且是Java相關程序引起的,若不是則排查其他問題,如系統問題。用docker運作top指令報錯“TERM environment variable not set.”,解決辦法是:在運作top時加上 -b參數。top -bc | top -b [pid]。

3、執行top (-b) -Hp ${pid}  (d指令指定每兩次螢幕資訊重新整理之間的時間間隔。步驟2中cpu或記憶體使用率過高的Java程序号)。若是接口反應慢問題,則可在此時請求接口,觀察得到持續占用CPU或記憶體使用率過高的線程号(用于後續步驟5)。    

    3.1、若cpu使用率過高,執行jstack ${pid} > jstack.log   (步驟2中pid程序号)。得到該Java程序的線程快照jstack.log。

         3.1.1、執行less jstack.log ,将之前有問題的(步驟3中)線程号轉換為16進制,線上程快照中查找到該線程,輸入: /16進制線程号(printf "%x\n"  可以得到16進制數)  enter  ,檢視其線程相關資訊,

                    查找與本服務密切相關的資訊(如自定義類),确定問題所在行,解決問題,重試。

                    若發現是JVM的垃圾回收線程。再搜尋整個檔案,沒有被死鎖的線程。于是懷疑記憶體沒有正确釋放,JAVA程序已使用的記憶體,已經達到了配置設定給JVM的最大記憶體。導緻垃圾回收頻繁執行FullGC,占用了CPU。

                    執行jstat -gccasue ${pid} ${refresh time} 【jstat -gccause 1 1000】若發現年輕代,老年代記憶體使用率太高。進一步證明之前的懷疑。jstat使用詳解 

     3.2、若記憶體使用率過高,執行jmap -histo:live ${pid}  | head -10 ,若還不能确定造成記憶體洩漏的類, 則執行jmap -dump:format=b,file=${dumpFileName} ${pid} 得到目前記憶體快照。

4. 使用eclipse的memory analyzer導入記憶體快照,進行分析。找出記憶體異常的對象。

5. 修改程式的BUG。

6. BUG修複以後,繼續定時擷取記憶體快照,持續觀察。直到徹底解決問題。

若是自己熟悉的代碼,通過業務日志與直覺往往也能比較快的定位到問題,很多次都是相信直覺,對于心中對代碼有比較熟悉的基礎上。

具體測試例子:subao-product  記憶體(MB):700~700 ,啟動指令:java -jar -Xms350m -Xmx350m -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/alidata1/admin/subao-product/heapdump.hprof subao-product.jar