天天看點

項目中如何排查JVM問題

作者:架構小哥

先分析,後排查

遇到這個問題,先不要急着說,我們一般通過什麼樣的工具來查找問題。凡事都有多面性,考慮問題也需要多面性地去思考。如主題,我們要去排查JVM問題時,肯定是系統出現了一些異常情況,比如CPU/記憶體飙升,我們需要去排查,又比如出現了OOM,程式自動重新開機了,我們沒了當時的環境,我們也需要去排查。是以我們先對情況分好類,再根據不同的分類使用不同的工具來進行排查工作。

一、當系統還能正常運作時

在系統還能正常運作時,我們能使用的工具就多了。

1、Java自帶的指令

  • 使用jps可以找到運作在伺服器上面所有的JVM程序以及啟動時的參數。如jps -vl這個指令中的-v代表輸出啟動JVM程序傳遞給JVM的參數,-l是輸出main方法所在類的完整路徑或者JAR包的完整路徑,如下圖:
項目中如何排查JVM問題
  • 可以使用jmap來檢視java堆(heap)的使用情況 ,如jmap -heap 19463,如圖:
項目中如何排查JVM問題
  • 可以通過 jstack 來檢視線程的運作情況,比如哪些線程阻塞、是否出現了死鎖。這指令很有用,能非常快速定位JAVA程式中運作卡頓和緩慢的性能問題。如 jstack -l 9739
項目中如何排查JVM問題
  • 可以通過jstat指令來檢視垃圾回收的情況,特别是fullgc,如果發現fullgc⽐較頻繁,那麼就得進行調優了。如jstat -gc jvm程序PID 2000
項目中如何排查JVM問題

以上的指令都在JDK的安裝目錄bin/下可以找到

項目中如何排查JVM問題

2、jvisualvm分析工具

這工具除了可以監控本地伺服器的資源使用情況,還可以監控遠端的。主要功能如下

1、監控本地Tomcat

2、監控遠端Tomcat

3、監控普通的JAVA程序

4、監控遠端springboot服務

3、阿裡提供的arthas

Arthas 是一款線上監控診斷産品,通過全局視角實時檢視應用 load、記憶體、gc、線程的狀态資訊,并能在不修改應用代碼的情況下,對業務問題進行診斷,包括檢視方法調用的出入參、異常,監測方法執行耗時,類加載資訊等,大大提升線上問題排查效率

常用指令:

  • dashboard - 目前系統的實時資料面闆
  • getstatic - 檢視類的靜态屬性
  • heapdump - dump java heap, 類似 jmap 指令的 heap dump 功能
  • jvm - 檢視目前 JVM 的資訊
  • logger - 檢視和修改 logger
  • mbean - 檢視 Mbean 的資訊
  • memory - 檢視 JVM 的記憶體資訊
  • ognl - 執行 ognl 表達式
  • perfcounter - 檢視目前 JVM 的 Perf Counter 資訊
  • sysenv - 檢視 JVM 的環境變量
  • sysprop - 檢視和修改 JVM 的系統屬性
  • thread - 檢視目前 JVM 的線程堆棧資訊
  • vmoption - 檢視和修改 JVM 裡診斷相關的 option
  • vmtool - 從 jvm 裡查詢對象,執行 forceGc

二、當系統發生OOM時

  1. 一般生産系統中都會設定當系統發生OOM時,生成當時的dump檔案(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs)
  2. 當拿到這個dump檔案時,可選擇對應的工具來對其進行分析

1、jvisualvm分析工具

把dump檔案導入到jvisualvm工具中進行分析,這工具可以分析當時發生OOM時,java程式當時的堆資訊、線程資訊、cpu資訊等,以一種可視化的圖形化界面展示出來,幫助我們更快地找到并解決總是。

項目中如何排查JVM問題

2、Memory Analyer(MAT)分析工具

MAT(Memory Analyzer Tool),一個基于Eclipse的記憶體分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查找記憶體洩漏和減少記憶體消耗。使用記憶體分析工具從衆多的對象中進行分析,快速的計算出在記憶體中對象的占用大小,看看是誰阻止了垃圾收集器的回收工作,并可以通過報表直覺的檢視到可能造成這種結果的對象。

跟jvisualvm差不多,也是通過導入hump檔案,來對jvm相關的資訊作出分析與建議

項目中如何排查JVM問題

3、線上分析工具

fastthread,這裡就不展開了,大家想要了解的話,可以自行度娘或google

總結

總的來說,不管是哪類情況(在運作的或OOM),我們需要借助以上提到的工具來輔助我們了解當時JVM發生了什麼情況,進而得到更多有效的資料來支撐我們對程式進行優化或參數調優。如存在大量對象,不被釋放,我們可以看看是不是代碼存在一些死循環的問題,一直向某個對象添加資料。比如程式頻繁地fullGC,那是不是我們設定的啟動參數不合理,年輕代設定了多少記憶體?老年代設定了多少記憶體?回收算法是否設定得當等。

不管是哪種工具,我們在項目中對JVM排查問題的套路都差不多。分析、推理、嘗試,總結、再分析,最終定位到具體問題