JVM問題排查步驟

sfhu發表於2020-12-17

 

 

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使用詳解 

     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

相關文章