大家好,我是Yuan,今天給大家介紹一款調優神器 -- 阿里巴巴Arthas,可以幫助你的應用釋放潛力。
1. 介紹
阿里巴巴 Arthas 是一個診斷工具,可以用于監視、分析和解決 Java 應用程序的問題。使用 Arthas 的一個主要優點是,我們不需要修改代碼,甚至不需要重新啟動我們想要監視的 Java 服務。
在本教程中,我們將首先安裝 Arthas,在此之后,通過一個簡單的案例來演示 Arthas 的一些關鍵特性。
最后,由于 Arthas 是用 Java 編寫的,因此它是跨平臺的,可以在 Linux、macOS 和 Windows 上運行。
2. 下載和入門
首先,我們可以通過直接下載鏈接或使用curl來下載 Arthas 庫:
curl?-O?https://alibaba.github.io/arthas/arthas-boot.jar
現在,讓我們通過運行帶有-h(幫助)選項的 Arthas 來測試它是否工作:
java?-jar?arthas-boot.jar?-h
如果成功,我們應該看到顯示所有命令的幫助指南:
3. 案例分析
在本教程中,我們將使用一個非常簡單的應用程序,基于利用遞歸實現的斐波那契數列的相對低效的實現方式:
public?class?FibonacciGenerator?{ ????public?static?void?main(String[]?args)?{ ????????System.out.println("按任意鍵繼續"); ????????System.in.read(); ????????for?(int?i?=?0;?i?100;?i++)?{ ????????????long?result?=?fibonacci(i); ????????????System.out.println(format("fib(%d):?%d",?i,?result)); ????????} ????} ????public?static?long?fibonacci(int?n)?{ ????????if?(n?==?0?||?n?==?1)?{ ????????????return?1L; ????????}?else?{ ????????????return?fibonacci(n?-?1)?+?fibonacci(n?-?2); ????????} ????} }
這個示例的最有趣的部分是遵循斐波那契數列的數學定義的 fibonacci 方法。
在 main 方法中,我們使用一個循環和相對較大的數字,以便讓計算機進行較長時間的計算。這當然正是我們想要的,以便演示 Arthas。
4. 啟動 Arthas
現在讓我們試試 Arthas!我們需要做的第一件事是運行我們的小型斐波那契應用程序。我們可以使用我們喜歡的 IDE 或直接在終端中運行它。它會要求按下一個鍵才能啟動。我們將在將進程附加到 Arthas 之后按下任意鍵。
現在,讓我們運行 Arthas 可執行文件:
java?-jar?arthas-boot.jar
Arthas 提示選擇要附加到的進程:
[INFO]?arthas-boot?version:?3.1.7 [INFO]?Found?existing?java?process,?please?choose?one?and?hit?RETURN. *?[1]:?25500?com.baeldung.arthas.FibonacciGenerator ...
讓我們選擇名稱為 com.baeldung.arthas.FibonacciGenerator 的進程。在此示例中,只需在列表中輸入數字‘1’并按 Enter 即可。
Arthas 現在會附加到該進程并啟動:
[INFO]?Try?to?attach?process?25500 [INFO]?Attach?process?25500?success. ...?????????????????????
一旦 Arthas 啟動,我們就有一個提示符,可以發出不同的命令。
我們可以使用 help 命令獲取有關可用選項的更多信息。為了方便使用 Arthas,我們還可以使用 tab 鍵來自動完成其命令。
在將 Arthas 附加到進程后,我們現在可以按下一個鍵,程序將開始打印斐波那契數。
5. 儀表盤
一旦 Arthas 啟動,我們可以使用儀表盤。在這種情況下,我們通過輸入 "dashboard" 命令來使用儀表盤。現在,我們可以看到一個詳細的屏幕,其中包含多個面板和關于我們的 Java 進程的許多信息:
讓我們更詳細地看一下其中的一些內容:
頂部區域專門顯示當前正在運行的線程
一個重要的列是每個線程的 CPU 使用情況
第三部分顯示每個線程的 CPU 時間
另一個有趣的面板是內存分析。不同的內存區域以及它們的統計信息都列在其中。在右側,我們有垃圾收集器的信息
最后,在第五部分,我們有關于主機平臺和 JVM 的信息
我們可以通過按下 "q" 鍵退出儀表盤。
我們應該記住,即使退出,Arthas 仍會附加到我們的進程上。因此,為了正確地從我們的進程中斷開它的連接,我們需要運行 "stop" 命令。
6. 分析堆棧跟蹤
在儀表盤中,我們看到我們的主進程占用了幾乎 100% 的 CPU。該進程的 ID 是 1,在第一列中可以看到。
現在我們已經退出了儀表盤,我們可以通過運行 "thread" 命令來更詳細地分析該進程:thread?1
作為參數傳遞的數字是線程 ID。Arthas 打印出一個堆棧跟蹤信息,其中充斥著對 fibonacci 方法的調用。
如果堆棧跟蹤信息很長而且難以閱讀,可以使用 "thread" 命令結合 "grep" 命令來過濾:
thread?1?|?grep?'main('
這將只打印與 "grep" 命令匹配的行:
[arthas@25500]$?thread?1?|?grep?'main('
????at?com.baeldung.arthas.FibonacciGenerator.main(FibonacciGenerator.java:10)
7. 反編譯Java類
假設我們正在分析一個我們對其中了解甚少或一無所知的Java應用程序,突然發現堆棧中充斥著以下類型的重復調用:
[arthas@59816]$?thread?1 "main"?Id=1?RUNNABLE ??at?app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18) ??at?app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18) ??...
由于我們運行了Arthas,我們可以反編譯一個類來查看其內容。為了實現這一點,我們可以使用jad命令,將限定類名作為參數傳遞:
jad?com.baeldung.arthas.FibonacciGenerator
類加載器: +-jdk.internal.loader.ClassLoaders?$?AppClassLoader?@?799f7e29 ??+-jdk.internal.loader.ClassLoaders?$?PlatformClassLoader?@?60f1dd34 位置: /home/amoreno/work/baeldung/tutorials/libraries-3/target/
/* ?*?反編譯使用CFR。 ?*/ package?com.baeldung.arthas; import?java.io.IOException; import?java.io.InputStream; importjava.io.PrintStream; public?class?FibonacciGenerator?{ ????public?static?void?main(String[]?arrstring)?throws?IOException?{
輸出是反編譯的Java類和一些有用的元數據,如類的位置。這是一個非常有用和強大的功能。
8. 搜索類和搜索方法
搜索類命令在搜索JVM中加載的類時非常方便。我們可以使用它通過輸入sc并將模式作為參數傳遞來使用,帶或不帶通配符:
[arthas@70099]$?sc?*Fibonacci* com.baeldung.arthas.FibonacciGenerator Affect(row-cnt:1)?cost?in?5?ms.
一旦我們獲得了類的限定名稱,我們可以使用兩個附加標志來查找更多信息:
-d顯示類的詳細信息
-f顯示類的字段
然而,類的字段必須與詳細信息一起查詢:
[arthas@70099]$?sc?-df?com.baeldung.arthas.FibonacciGenerator ??class-info????????com.baeldung.arthas.FibonacciGenerator ??...
同樣,我們可以使用sm(搜索方法)命令來查找類中加載的方法。在這種情況下,對于我們的類com.baeldung.arthas.FibonacciGenerator,我們可以運行:
[arthas@70099]$?sm?com.baeldung.arthas.FibonacciGenerator com.baeldung.arthas.FibonacciGenerator?()V com.baeldung.arthas.FibonacciGenerator?main([Ljava/lang/String;)V com.baeldung.arthas.FibonacciGenerator?fibonacci(I)J Affect(row-cnt:3)?cost?in?4?ms.
我們可以使用-d標志來檢索方法的詳細信息。最后,我們可以傳遞方法的名稱作為可選參數,以縮小返回方法的數量:
sm?-d?com.baeldung.arthas.FibonacciGenerator?fibonacci ?declaring-class??com.baeldung.arthas.FibonacciGenerator ?method-name??????fibonacci ?modifier?????????public,static ?annotation ?parameters???????int ?return???????????long ?exceptions ?classLoaderHash??799f7e29
9. 監視方法調用
我們可以使用Arthas來監視方法,這在調試應用程序的性能問題時非常方便。為此,我們可以使用monitor命令。
monitor命令需要一個-c <秒數>標志和兩個參數 - 限定類名和方法名。
對于我們的案例研究,讓我們來調用monitor:
monitor?-c?10?com.baeldung.arthas.FibonacciGenerator?fibonacci
正如我們所預期的,Arthas將每10秒打印有關fibonacci方法的指標:
Affect(class-cnt:1?,?method-cnt:1)?cost?in?47?ms. ?timestamp????????????class??????????????????????????????????????????method?????total???success??fail??avg-rt(ms)??fail-rate??????????????????????????????????????????????????????????????????????? -----------------------------------------------------------------------------------------------------------------------------?????????????????????????????????????????????????????????????????????? ?2020-03-07?1126??com.baeldung.arthas.FibonacciGenerator??fibonacci??528957??528957???0?????0.07????????0.00% ...???????????????????????????????????????????????????????????????????????????對于那些最終失敗的調用,我們也有指標 - 這對于調試很有用。
10. 監控方法參數
如果我們需要調試方法的參數,我們可以使用watch命令。但是,語法會稍微復雜一些:
watch?com.baeldung.arthas.FibonacciGenerator?fibonacci?'{params[0],?returnObj}'?'params[0]>10'?-n?10
讓我們詳細看一下各個參數:
第一個參數是類名
第二個參數是方法名
第三個參數是定義我們要查看的內容的OGNL表達式 - 在這種情況下,它是第一個(也是唯一的)方法參數和返回值
第四個和最后一個可選參數是用于過濾我們要監視的調用的布爾表達式
對于此示例,我們只想在參數大于10時監視。最后,我們添加一個標志來限制結果為10個:
watch?com.baeldung.arthas.FibonacciGenerator?fibonacci?'{params[0],?returnObj}'?'params[0]>10'?-n?10 按Q或Ctrl+C中斷。 Affect(class-cnt:1?,?method-cnt:1)?cost?in?19?ms. ts=2020-02-17?2108;?[cost=30.165211ms]?result=@ArrayList[ ????@Integer[11], ????@Long[144], ] ts=2020-02-17?2108;?[cost=50.405506ms]?result=@ArrayList[ ????@Integer[12], ????@Long[233], ] ...
在這里,我們可以看到帶有CPU時間和輸入/返回值的調用示例。
11. 分析器
對于那些對應用程序性能感興趣的人來說,通過分析器命令提供了一種非常直觀的能力。分析器將評估我們的進程正在使用的CPU的性能。
讓我們通過運行profiler start來啟動分析器。這是一個非阻塞的任務,意味著在分析器工作時我們可以繼續使用Arthas。
隨時可以通過運行profiler getSamples來詢問分析器有多少個樣本。
現在讓我們使用profiler stop來停止分析器。此時,一個FlameGraph圖像將被保存。在這個具體的案例中,我們有一個以斐波那契線程為主導的圖表:
注意,當我們想要檢測我們的CPU時間花在哪里時,這個圖表特別有用。
12. 總結
在本教程中,我們探索了Arthas的一些最強大和有用的功能。
正如我們所見,Arthas有許多命令可以幫助我們診斷各種問題。當我們無法訪問正在審查的應用程序的代碼,或者我們想快速診斷在服務器上運行的有問題的應用程序時,它也可以特別有幫助。
編輯:黃飛
?
評論
查看更多