Arthas 是Alibaba開源的Java診斷工具,深受開發者喜好html
當你遇到如下相似問題而一籌莫展時,Arthas能夠幫助你解決:java
Arthas支持JDK 6+,支持Linux/Mac/Winodws,採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷git
Arthas提供的功能主要能夠分爲如下3個方面:程序員
下載arthas-boot.jar,而後用java -jar的方式啓動:github
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
複製代碼
而後輸入進程對應編號,進入Arthas的命令交互界面便可使用:tomcat
打印幫助信息:bash
java -jar arthas-boot.jar -h
複製代碼
下面介紹Arthas的一些經常使用的命令和用法和原理,看看是如何解決咱們實際中的問題的,命令詳情能夠參考Arthas的官方文檔markdown
在arthas的命令行界面,輸入dashboard命令,會實時展現當前tomcat的多線程狀態、JVM各區域、GC狀況等信息 多線程
輸入thread命令,會顯示全部線程的狀態信息 輸入thread -n 3會顯示當前最忙的3個線程,能夠用來排查線程CPU消耗 輸入thread -b 會顯示當前處於BLOCKED狀態的線程,能夠排查線程鎖的問題 框架
輸入jvm命令,查看jvm詳細的性能數據
有時排查問題中咱們須要查看參數,返回值,一般的須要加日誌打印,比較繁瑣,基於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], ], ] 複製代碼
有時會遇到服務卡頓,想排查到底哪一個步驟耗時比較久,一般作法是加日誌,使用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() 複製代碼
總體宏觀模塊調用圖以下:
篇幅緣由,下面對其其中涉及的比較核心的2個原理進行簡單介紹:
JDK提供的JMX(Java Management Extensions Java管理擴展,是一個爲應用程序植入管理功能的框架),JMX管理管理了一系列MBean對象,Arthas正是基於這些MBean對象實現內存、GC、類加載信息、JVM信息監控
從JDK5以後,引入了java.lang.Instrument,程序員經過修改方法的字節碼實現動態修改類代碼。在代理類的方法中的參數中,就有Instrumentation inst實例。經過該實例,咱們能夠調用Instrumentation提供的各類接口。好比調用inst.getAllLoadedClasses()獲得全部已經加載過的類。調用inst.addTransformer(new SdlTransformer(), true)新增轉換器。調用inst.retransformClasses(Class cls),向JVM發起重轉換請求
Arthas使用ASM生成加強後的類的字節碼,加強的功能包括方法調用入參、返回值查看、方法調用統計、方法調用記錄和重作,再基於JDK提供的Instrumentation接口對方法進行增長和轉換
Arthas官方文檔提供了許多用戶案例,下面介紹幾個比較有意思的案例:
服務應用運行中有時會出現一些奇怪日誌,排查定位這些日誌的來源比較麻煩 經過修改StringBuilder的實現代碼打印出日誌的調用堆棧信息,編譯生成StringBuilder.clss,再基於Arthas提供的redefine命令修改應用中使用的StringBuilder的實際使用字節碼
頁面訪問返回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. 複製代碼
有時爲了快速驗證線上問題的修復方案,或者爲了快速測試,咱們須要熱更新代碼 Arthas提供的解決步驟以下