幾個必會的JDK效能監控和故障處理工具

👉 這是一個或許對你有用的社群
🐱 一對一交流/面試小冊/簡歷最佳化/求職解惑,歡迎加入芋道快速開發平臺知識星球。下面是星球提供的部分資料:
👉這是一個或許對你有用的開源專案
國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。
功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERPCRMAI 大模型等等功能:
  • Boot 多模組架構:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 微服務架構:https://gitee.com/zhijiantianya/yudao-cloud
  • 影片教程:https://doc.iocoder.cn
【國內首批】支援 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 雙版本 

雖然阿里巴巴的 Arthas 這個工具很強大,不過如果你能夠熟練使用 JDK 提供的工具,那麼在不借助任何外力的情況下,就可以非常輕鬆的進行應用的效能監控和故障處理。
JDK 提供的工具,大家最熟悉的估計就是 java 和 javac 這兩個了,然而 JDK 實際上提供了非常強大的效能監控和除錯工具,今天松哥就來和大家一起捋一捋這些工具。

一 jps

這個應該是大家最為熟悉的工具了,使用這個命令可以快速列出來系統上正在執行的 Java 程序。
這個命令在執行的時候一般有四個引數:
  • -q 表示只輸出程序 ID,不輸出主類名稱,準確來說,這裡輸出的叫做本地虛擬機器程序 ID(LVMID),不過對於本地虛擬機器程序來說,LVMID 和作業系統的程序 ID 是一致的。
  • -l 表示輸出主類的全名,如果程序執行的是 jar 包,那麼就輸出 jar 包的完整路徑。
  • -m 表示輸出程序啟動時傳遞給 main() 函式的引數。
  • -v 表示輸出程序啟動時的 JVM 引數。
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 影片教程:https://doc.iocoder.cn/video/

二 jstat

jstat 是用來監控虛擬機器各種執行狀態資訊的命令列工具,這個工具可以用來檢視本地或者遠端虛擬機器記憶體、垃圾收集、即時編譯等等資訊。
一般來說,這些資料我們可以藉助視覺化工具來檢視,例如 JMC 或者 VisualVM 等等,但是有時候在伺服器環境下,在命令列環境下沒法執行 GUI 圖形介面,那麼此時 jstat 是一個不錯的選擇。
jstat 執行引數比較多,松哥這裡列舉幾個比較常見的引數:
  • -class 這個表示監視類載入、解除安裝數量、總空間以及類裝載所耗費的時間。
  • -gc 這個表示監視 Java 堆狀況,包括 Eden 區,兩個 Survivor 區、老年代以及永久帶的容量,已使用的空間以及垃圾收集時間合計等等資訊。
命令中的 1s 8 表示每秒列印一次,一共列印 8 次,如果不設定,則列印一次。
這裡輸出的各引數含義如下:
S0C:Survivor0 的容量。S1C:Survivor1 的容量。S0U:Survivor0 已使用大小。S1U:Survivor1 已使用大小。EC:Eden 區容量。EU:Eden 區已使用大小。OC:老年代容量。OU:老年代已使用大小。MC:元資料區容量。MU:元資料區已使用大小。CCSC:壓縮類空間容量。CCSU:壓縮類空間已使用大小。YGC:年輕代垃圾回收次數。YGCT:年輕代垃圾回收總耗時。FGC:FullGC 次數。FGCT:FullGC 總耗時。CGC:GC STW 的次數。CGCT:GC STW 的時間。GCT:總 GC 時間。
基本上我們想知道的關於 JVM 執行記憶體狀態的資訊,這裡都有了。
  • -gccapacity 這個監控內容與 -gc 類似,不過輸出內容主要關注 Java 堆各個區域使用到的最大最小空間。
這裡涉及到的引數我也和大家稍微解釋下:
NGCMN:新生代最小容量。NGCMX:新生代最大容量。NGC:新生代當前容量。OGCMN:老年代最小容量。OGCMX:老年代最大容量。OGC:老年代當前容量。MCMN:元空間最小容量。MCMX:元空間最大容量。CCSMN:壓縮類空間最小容量。CCSMX:壓縮類空間最大容量。CCSC:壓縮類空間當前容量。
補充輸出內容和前面一致的我就不重複解釋了。
  • -gcutil 這個和 -gc 類似,不過輸出的內容主要關注已使用的空間佔總空間的比例。
S0:Survivor0 區使用比例。S1:Survivor1 區使用比例。E:Eden 區使用比例。O:老年代使用比例。M:元空間使用比例。CCS:壓縮類空間使用比例。
這塊能加的引數實際上非常多,對於我們來說比較常用的主要就是上面這幾個命令。
如果小夥伴們想要檢視完整指令,可以參考官方文件:https://docs.oracle.com/en/java/javase/11/tools/jstat.html
基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/yudao-cloud
  • 影片教程:https://doc.iocoder.cn/video/

三 jinfo

jinfo 命令可以即時檢視和修改 JVM 各項引數。
能修改這就很牛了。
平時我們啟動一個 Java 專案,一旦啟動之後,如果想要知道專案啟動時的各項 JVM 引數,那麼就只能去查文件了。但是如果你能夠熟練使用 jinfo,那麼這個事情就容易很多了。
直接 jinfo pid 就會展示出來所有的 JVM 引數。
如果只想檢視某一個 JVM 引數,那麼可以使用如下命令:

jinfo -flag CICompilerCount 28893

也可以在不重啟 JVM 引數的情況下,動態修改 JVM 引數。
例如松哥這裡的案例,原本是沒有開啟 PrintClassHistogram 的,我現在動態開啟:
PrintClassHistogram 前面沒有符號,表示檢視當前狀態;PrintClassHistogram 前面有個 + 表示開啟;PrintClassHistogram 前面有個 - 表示關閉。
這種方式是修改 value 為 boolean 的 JVM 引數,如果是 key-value 格式的 JVM 引數,那麼可以按照下面這種方式修改:
當然這個修改並非所有的 JVM 引數都能改,至於哪些 JVM 引數能改,我們可以執行 java -XX:+PrintFlagsInitial 命令,找到標記為 manageable 的引數,這些引數是可以動態修改的。
另外我們在程式碼中透過 System.getProperties() 獲取到的屬性,也可以透過指令打印出來:

jinfo -sysprops 57002

四 jmap

jmap 命令一般可以用來生成 heapdump。
這個命令在新版本 JDK 中執行的時候,前面要加上 jhsdb。
從這裡我們可以解讀出哪些資訊呢?
  • 可以看到最大可分配的 Heap 大小(MaxHeapSize)
  • 可以看到 JVM 啟動時分配的新生代記憶體(NewSize)
  • 可以看到可分配的最大新生代記憶體(MaxNewSize)
  • 可以看到 JVM 啟動時分配的老年代大小(OldSize)
  • 可以看到老年代和新生代的記憶體比例(NewRatio),上面截圖中表示 老/新=2,即老年代佔 2/3,新生代佔 1/3。
  • 可以看到新生代中 Eden 區和一個 Survivor 區的比例(SurvivoRatio)
  • 可以看到初始的 Metaspace 大小(MetaspaceSize)
  • 可以看到最大的 Metaspace 大小(MaxMetaspaceSize)
  • 可以看到在 G1 收集器下,每個 Region 的大小(G1HeapRegionSize)
下面的這些就好理解了,分別是不同區域的 regions 數量、總空間、使用空間以及空閒空間。
也可以利用 jmap 檢視 Heap 中物件的統計資訊,比如物件的數量、佔用記憶體的大小以及類的完整路徑。

jmap -histo:live pid

加上 :live 表示檢視活著的物件資訊。
也可以檢視 Heap 中元空間的類載入資訊 jmap -clstats 28893
這裡可以看到有哪些類載入器,分別載入了哪些類。
當然,最重要的功能是生成 dump 檔案了:
這裡幾個引數說明一下:
  • live 表示只轉存堆中活動物件,如果沒有制定,則存所有物件。
  • format=b 表示以 hprof 二進位制格式轉存。
  • file=xxx 表示生成的檔名。
生成的檔案,可以使用 idea 開啟檢視。
小技巧:獲取 heapdump 還有哪些方式?
  1. 使用 kill -3 嚇一嚇 JVM,就能拿到堆轉儲快照。
  2. -XX:HeapDumpOnOutOfMemoryError 引數可以讓虛擬機器在記憶體溢位時自動生成堆轉儲快照。

五 jhat

這個工具目前已經廢棄了。
松哥這裡就簡單說下這個工具的作用以及替代品。
前面 jmap 會生成 heapdump 檔案,這是一個二進位制檔案,那麼我們透過什麼工具去分析這個檔案呢?比如可以使用 Eclipse 的 MAT,當然現在 IDEA 也可以直接開啟這個檔案分析,這塊成熟的工具還是非常多的。
那麼 jhat 其實也是一個這樣的工具,jhat 內建了一個微型的 Web 伺服器,讓開發者可以在瀏覽器中檢視相關資料。但是因為 jhat 功能比較簡陋,所以目前已經廢棄了。

六 jstack

jstack 可以檢視 JVM 當前時刻的執行緒快照。
如果某個執行緒執行比較耗時,或者發生死鎖,發生死迴圈等,那麼就可以透過這個指令來檢視各個執行緒的呼叫堆疊,檢查到底發生了什麼問題。
-l 表示出了堆疊之外,也把鎖的相關資訊顯示出來。
不過這個命令松哥並不常用。因為 Thread 中有一個 getAllStackTraces 方法,我們透過 jstack 命令獲取到的資訊基本上透過這個方法都能獲取到,所以可以自己結合這個方法寫監控頁面檢視相關資訊。

歡迎加入我的知識星球,全面提升技術能力。
👉 加入方式,長按”或“掃描”下方二維碼噢
星球的內容包括:專案實戰、面試招聘、原始碼解析、學習路線。
文章有幫助的話,在看,轉發吧。
謝謝支援喲 (*^__^*)

相關文章