Java診斷利器Arthas

分散式系統架構發表於2019-09-25

Arthas

1 簡介

Arthas 是Alibaba開源的Java診斷工具,深受開發者喜愛

當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決:

  • 這個類從哪個 jar 包載入的?為什麼會報各種類相關的 Exception?
  • 我改的程式碼為什麼沒有執行到?難道是我沒 commit?分支搞錯了?
  • 遇到問題無法線上上 debug,難道只能通過加日誌再重新發布嗎?
  • 線上遇到某個使用者的資料處理有問題,但線上同樣無法 debug,線下無法重現!
  • 是否有一個全域性視角來檢視系統的執行狀況?
  • 有什麼辦法可以監控到JVM的實時執行狀態?

Arthas支援JDK 6+,支援Linux/Mac/Winodws,採用命令列互動模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷

2 主要功能

Arthas提供的功能主要可以分為以下3個方面:

  • (1) 資訊監控
    • 程式執行基本資訊:記憶體、CPU佔用、執行緒資訊、執行緒堆疊、執行緒數統計、環境變數資訊
    • 物件資訊:類物件靜態屬性、 Mbean 的屬性資訊、已載入類資訊、類載入器、類方法資訊
  • (2) 方法呼叫
    • 方法呼叫入參、返回值檢視
    • 方法被呼叫的呼叫路徑、呼叫耗時、方法呼叫次數、成功次數、失敗次數等統計
    • 記錄和重做方法呼叫
  • (3) 類檔案處理
    • dump已載入類的位元組碼、位元組碼反編譯、類編譯、類重新熱載入

3 安裝和使用

3.1 安裝

下載arthas-boot.jar,然後用java -jar的方式啟動:

wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
複製程式碼

然後輸入程式對應編號,進入Arthas的命令互動介面即可使用:

Java診斷利器Arthas

列印幫助資訊:

java -jar arthas-boot.jar -h
複製程式碼

3.2 使用

下面介紹Arthas的一些常用的命令和用法和原理,看看是如何解決我們實際中的問題的,命令詳情可以參考Arthas的官方文件

(1) 整體dashboard資料

在arthas的命令列介面,輸入dashboard命令,會實時展示當前tomcat的多執行緒狀態、JVM各區域、GC情況等資訊

dashboard

(2) 檢視執行緒監控

輸入thread命令,會顯示所有執行緒的狀態資訊 輸入thread -n 3會顯示當前最忙的3個執行緒,可以用來排查執行緒CPU消耗 輸入thread -b 會顯示當前處於BLOCKED狀態的執行緒,可以排查執行緒鎖的問題

thread

(3) JVM監控

輸入jvm命令,檢視jvm詳細的效能資料

jvm

(4) 觀察方法引數、返回值

有時排查問題中我們需要檢視引數,返回值,通常的需要加日誌列印,比較繁瑣,基於watch命令我們可以很方便做到這一切

$ watch demo.MathGame primeFactors "{params,returnObj}" -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 44 ms.
ts=2018-12-03 19:16:51; [cost=1.280502ms] result=@ArrayList[
    @Object[][
        @Integer[535629513],
    ],
    @ArrayList[
        @Integer[3],
        @Integer[19],
        @Integer[191],
        @Integer[49199],
    ],
]
複製程式碼

(5) 觀察方法呼叫路徑,耗時詳情

有時會遇到服務卡頓,想排查到底哪個步驟耗時比較久,通常做法是加日誌,使用trace命令可以很方便解決這個問題:

$ trace demo.MathGame run
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
`---ts=2018-12-04 00:44:17;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[10.611029ms] demo.MathGame:run()
        +---[0.05638ms] java.util.Random:nextInt()
        +---[10.036885ms] demo.MathGame:primeFactors()
        `---[0.170316ms] demo.MathGame:print()
複製程式碼

4 實現原理

整體巨集觀模組呼叫圖如下:

整體模組呼叫圖

篇幅原因,下面對其其中涉及的比較核心的2個原理進行簡單介紹:

(1) 資訊監控、類檔案處理

JDK提供的JMX(Java Management Extensions Java管理擴充套件,是一個為應用程式植入管理功能的框架),JMX管理管理了一系列MBean物件,Arthas正是基於這些MBean物件實現記憶體、GC、類載入資訊、JVM資訊監控

(2) 方法呼叫

從JDK5之後,引入了java.lang.Instrument,程式設計師通過修改方法的位元組碼實現動態修改類程式碼。在代理類的方法中的引數中,就有Instrumentation inst例項。通過該例項,我們可以呼叫Instrumentation提供的各種介面。比如呼叫inst.getAllLoadedClasses()得到所有已經載入過的類。呼叫inst.addTransformer(new SdlTransformer(), true)新增轉換器。呼叫inst.retransformClasses(Class cls),向JVM發起重轉換請求

Arthas使用ASM生成增強後的類的位元組碼,增強的功能包括方法呼叫入參、返回值檢視、方法呼叫統計、方法呼叫記錄和重做,再基於JDK提供的Instrumentation介面對方法進行增加和轉換

5 實戰案例

Arthas官方文件提供了許多使用者案例,下面介紹幾個比較有意思的案例:

(1) 排查應用奇怪日誌來源 案例詳情

服務應用執行中有時會出現一些奇怪日誌,排查定位這些日誌的來源比較麻煩 通過修改StringBuilder的實現程式碼列印出日誌的呼叫堆疊資訊,編譯生成StringBuilder.clss,再基於Arthas提供的redefine命令修改應用中使用的StringBuilder的實際使用位元組碼

(2) 排查SpringBoot應用401/404問題 案例詳情

頁面訪問返回401/404,碰到這種問題時,通常很頭痛,特別是線上上環境時 通過Arthas提供的trace命令,列印出頁面訪問時的完整請求樹,定位出具體哪個Servlet返回404

$ trace javax.servlet.Servlet *
Press Ctrl+C to abort.
Affect(class-cnt:7 , method-cnt:185) cost in 1018 ms.
複製程式碼

通過trace命令,trace物件是javax.servlet.Filter定位具體哪個Filter攔截請求定位返回401的問題來源

$ trace javax.servlet.Filter *
Press Ctrl+C to abort.
Affect(class-cnt:13 , method-cnt:75) cost in 278 ms.
複製程式碼

(3) 線上程式碼熱更新 案例詳情

有時為了快速驗證線上問題的修復方案,或者為了快速測試,我們需要熱更新程式碼 Arthas提供的解決步驟如下

  • 步驟1 jad命令反編譯程式碼
  • 步驟2 文字編輯器修改程式碼
  • 步驟3 sc命令查詢程式碼所在類的ClassLoader
  • 步驟4 mc命令指定ClassLoader編譯程式碼
  • 步驟5 redefine命令熱更新程式碼

參考

Arthas官方文件

Arthas快速入門

6到飛起的Java診斷工具Arthas

解密阿里線上問題診斷工具Arthas和jvm-sandbox

Java診斷利器Arthas

相關文章