大家好,我是Yuan,今天給大家介紹一款調(diào)優(yōu)神器 -- 阿里巴巴Arthas,可以幫助你的應(yīng)用釋放潛力。
1. 介紹
阿里巴巴 Arthas 是一個診斷工具,可以用于監(jiān)視、分析和解決 Java 應(yīng)用程序的問題。使用 Arthas 的一個主要優(yōu)點是,我們不需要修改代碼,甚至不需要重新啟動我們想要監(jiān)視的 Java 服務(wù)。
在本教程中,我們將首先安裝 Arthas,在此之后,通過一個簡單的案例來演示 Arthas 的一些關(guān)鍵特性。
最后,由于 Arthas 是用 Java 編寫的,因此它是跨平臺的,可以在 Linux、macOS 和 Windows 上運行。
2. 下載和入門
首先,我們可以通過直接下載鏈接或使用curl來下載 Arthas 庫:
curl-Ohttps://alibaba.github.io/arthas/arthas-boot.jar
現(xiàn)在,讓我們通過運行帶有-h(幫助)選項的 Arthas 來測試它是否工作:
java-jararthas-boot.jar-h
如果成功,我們應(yīng)該看到顯示所有命令的幫助指南:
3. 案例分析
在本教程中,我們將使用一個非常簡單的應(yīng)用程序,基于利用遞歸實現(xiàn)的斐波那契數(shù)列的相對低效的實現(xiàn)方式:
publicclassFibonacciGenerator{
publicstaticvoidmain(String[]args){
System.out.println("按任意鍵繼續(xù)");
System.in.read();
for(inti=0;i100;i++){
longresult=fibonacci(i);
System.out.println(format("fib(%d):%d",i,result));
}
}
publicstaticlongfibonacci(intn){
if(n==0||n==1){
return1L;
}else{
returnfibonacci(n-1)+fibonacci(n-2);
}
}
}
這個示例的最有趣的部分是遵循斐波那契數(shù)列的數(shù)學(xué)定義的 fibonacci 方法。
在 main 方法中,我們使用一個循環(huán)和相對較大的數(shù)字,以便讓計算機(jī)進(jìn)行較長時間的計算。這當(dāng)然正是我們想要的,以便演示 Arthas。
4. 啟動 Arthas
現(xiàn)在讓我們試試 Arthas!我們需要做的第一件事是運行我們的小型斐波那契應(yīng)用程序。我們可以使用我們喜歡的 IDE 或直接在終端中運行它。它會要求按下一個鍵才能啟動。我們將在將進(jìn)程附加到 Arthas 之后按下任意鍵。
現(xiàn)在,讓我們運行 Arthas 可執(zhí)行文件:
java-jararthas-boot.jar
Arthas 提示選擇要附加到的進(jìn)程:
[INFO]arthas-bootversion:3.1.7
[INFO]Foundexistingjavaprocess,pleasechooseoneandhitRETURN.
*[1]:25500com.baeldung.arthas.FibonacciGenerator
...
讓我們選擇名稱為 com.baeldung.arthas.FibonacciGenerator 的進(jìn)程。在此示例中,只需在列表中輸入數(shù)字‘1’并按 Enter 即可。
Arthas 現(xiàn)在會附加到該進(jìn)程并啟動:
[INFO]Trytoattachprocess25500
[INFO]Attachprocess25500success.
...
一旦 Arthas 啟動,我們就有一個提示符,可以發(fā)出不同的命令。
我們可以使用 help 命令獲取有關(guān)可用選項的更多信息。為了方便使用 Arthas,我們還可以使用 tab 鍵來自動完成其命令。
在將 Arthas 附加到進(jìn)程后,我們現(xiàn)在可以按下一個鍵,程序?qū)㈤_始打印斐波那契數(shù)。
5. 儀表盤
一旦 Arthas 啟動,我們可以使用儀表盤。在這種情況下,我們通過輸入 "dashboard" 命令來使用儀表盤。現(xiàn)在,我們可以看到一個詳細(xì)的屏幕,其中包含多個面板和關(guān)于我們的 Java 進(jìn)程的許多信息:
讓我們更詳細(xì)地看一下其中的一些內(nèi)容:
- 頂部區(qū)域?qū)iT顯示當(dāng)前正在運行的線程
- 一個重要的列是每個線程的 CPU 使用情況
- 第三部分顯示每個線程的 CPU 時間
- 另一個有趣的面板是內(nèi)存分析。不同的內(nèi)存區(qū)域以及它們的統(tǒng)計信息都列在其中。在右側(cè),我們有垃圾收集器的信息
- 最后,在第五部分,我們有關(guān)于主機(jī)平臺和 JVM 的信息
我們可以通過按下 "q" 鍵退出儀表盤。
我們應(yīng)該記住,即使退出,Arthas 仍會附加到我們的進(jìn)程上。因此,為了正確地從我們的進(jìn)程中斷開它的連接,我們需要運行 "stop" 命令。
6. 分析堆棧跟蹤
在儀表盤中,我們看到我們的主進(jìn)程占用了幾乎 100% 的 CPU。該進(jìn)程的 ID 是 1,在第一列中可以看到。
現(xiàn)在我們已經(jīng)退出了儀表盤,我們可以通過運行 "thread" 命令來更詳細(xì)地分析該進(jìn)程:
thread1
作為參數(shù)傳遞的數(shù)字是線程 ID。Arthas 打印出一個堆棧跟蹤信息,其中充斥著對 fibonacci 方法的調(diào)用。
如果堆棧跟蹤信息很長而且難以閱讀,可以使用 "thread" 命令結(jié)合 "grep" 命令來過濾:
thread1|grep'main('
這將只打印與 "grep" 命令匹配的行:
[arthas@25500]$thread1|grep'main('
atcom.baeldung.arthas.FibonacciGenerator.main(FibonacciGenerator.java:10)
7. 反編譯Java類
假設(shè)我們正在分析一個我們對其中了解甚少或一無所知的Java應(yīng)用程序,突然發(fā)現(xiàn)堆棧中充斥著以下類型的重復(fù)調(diào)用:
[arthas@59816]$thread1
"main"Id=1RUNNABLE
atapp//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
atapp//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
...
由于我們運行了Arthas,我們可以反編譯一個類來查看其內(nèi)容。為了實現(xiàn)這一點,我們可以使用jad命令,將限定類名作為參數(shù)傳遞:
jadcom.baeldung.arthas.FibonacciGenerator
類加載器:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@799f7e29
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@60f1dd34
位置:
/home/amoreno/work/baeldung/tutorials/libraries-3/target/
/*
*反編譯使用CFR。
*/
packagecom.baeldung.arthas;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.PrintStream;
publicclassFibonacciGenerator{
publicstaticvoidmain(String[]arrstring)throwsIOException{
輸出是反編譯的Java類和一些有用的元數(shù)據(jù),如類的位置。這是一個非常有用和強(qiáng)大的功能。
8. 搜索類和搜索方法
搜索類命令在搜索JVM中加載的類時非常方便。我們可以使用它通過輸入sc并將模式作為參數(shù)傳遞來使用,帶或不帶通配符:
[arthas@70099]$sc*Fibonacci*
com.baeldung.arthas.FibonacciGenerator
Affect(row-cnt:1)costin5ms.
一旦我們獲得了類的限定名稱,我們可以使用兩個附加標(biāo)志來查找更多信息:
- -d顯示類的詳細(xì)信息
- -f顯示類的字段
然而,類的字段必須與詳細(xì)信息一起查詢:
[arthas@70099]$sc-dfcom.baeldung.arthas.FibonacciGenerator
class-infocom.baeldung.arthas.FibonacciGenerator
...
同樣,我們可以使用sm(搜索方法)命令來查找類中加載的方法。在這種情況下,對于我們的類com.baeldung.arthas.FibonacciGenerator,我們可以運行:
[arthas@70099]$smcom.baeldung.arthas.FibonacciGenerator
com.baeldung.arthas.FibonacciGenerator()V
com.baeldung.arthas.FibonacciGeneratormain([Ljava/lang/String;)V
com.baeldung.arthas.FibonacciGeneratorfibonacci(I)J
Affect(row-cnt:3)costin4ms.
我們可以使用-d標(biāo)志來檢索方法的詳細(xì)信息。最后,我們可以傳遞方法的名稱作為可選參數(shù),以縮小返回方法的數(shù)量:
sm-dcom.baeldung.arthas.FibonacciGeneratorfibonacci
declaring-classcom.baeldung.arthas.FibonacciGenerator
method-namefibonacci
modifierpublic,static
annotation
parametersint
returnlong
exceptions
classLoaderHash799f7e29
9. 監(jiān)視方法調(diào)用
我們可以使用Arthas來監(jiān)視方法,這在調(diào)試應(yīng)用程序的性能問題時非常方便。為此,我們可以使用monitor命令。
monitor命令需要一個-c <秒數(shù)>標(biāo)志和兩個參數(shù) - 限定類名和方法名。
對于我們的案例研究,讓我們來調(diào)用monitor:
monitor-c10com.baeldung.arthas.FibonacciGeneratorfibonacci
正如我們所預(yù)期的,Arthas將每10秒打印有關(guān)fibonacci方法的指標(biāo):
Affect(class-cnt:1,method-cnt:1)costin47ms.
timestampclassmethodtotalsuccessfailavg-rt(ms)fail-rate
-----------------------------------------------------------------------------------------------------------------------------
2020-03-071126com.baeldung.arthas.FibonacciGeneratorfibonacci52895752895700.070.00%
...
對于那些最終失敗的調(diào)用,我們也有指標(biāo) - 這對于調(diào)試很有用。
10. 監(jiān)控方法參數(shù)
如果我們需要調(diào)試方法的參數(shù),我們可以使用watch命令。但是,語法會稍微復(fù)雜一些:
watchcom.baeldung.arthas.FibonacciGeneratorfibonacci'{params[0],returnObj}''params[0]>10'-n10
讓我們詳細(xì)看一下各個參數(shù):
- 第一個參數(shù)是類名
- 第二個參數(shù)是方法名
- 第三個參數(shù)是定義我們要查看的內(nèi)容的OGNL表達(dá)式 - 在這種情況下,它是第一個(也是唯一的)方法參數(shù)和返回值
- 第四個和最后一個可選參數(shù)是用于過濾我們要監(jiān)視的調(diào)用的布爾表達(dá)式
對于此示例,我們只想在參數(shù)大于10時監(jiān)視。最后,我們添加一個標(biāo)志來限制結(jié)果為10個:
watchcom.baeldung.arthas.FibonacciGeneratorfibonacci'{params[0],returnObj}''params[0]>10'-n10
按Q或Ctrl+C中斷。
Affect(class-cnt:1,method-cnt:1)costin19ms.
ts=2020-02-172108;[cost=30.165211ms]result=@ArrayList[
@Integer[11],
@Long[144],
]
ts=2020-02-172108;[cost=50.405506ms]result=@ArrayList[
@Integer[12],
@Long[233],
]
...
在這里,我們可以看到帶有CPU時間和輸入/返回值的調(diào)用示例。
11. 分析器
對于那些對應(yīng)用程序性能感興趣的人來說,通過分析器命令提供了一種非常直觀的能力。分析器將評估我們的進(jìn)程正在使用的CPU的性能。
讓我們通過運行profiler start來啟動分析器。這是一個非阻塞的任務(wù),意味著在分析器工作時我們可以繼續(xù)使用Arthas。
隨時可以通過運行profiler getSamples來詢問分析器有多少個樣本。
現(xiàn)在讓我們使用profiler stop來停止分析器。此時,一個FlameGraph圖像將被保存。在這個具體的案例中,我們有一個以斐波那契線程為主導(dǎo)的圖表:
注意,當(dāng)我們想要檢測我們的CPU時間花在哪里時,這個圖表特別有用。
12. 總結(jié)
在本教程中,我們探索了Arthas的一些最強(qiáng)大和有用的功能。
正如我們所見,Arthas有許多命令可以幫助我們診斷各種問題。當(dāng)我們無法訪問正在審查的應(yīng)用程序的代碼,或者我們想快速診斷在服務(wù)器上運行的有問題的應(yīng)用程序時,它也可以特別有幫助。
-
JAVA
+關(guān)注
關(guān)注
19文章
2952瀏覽量
104477 -
阿里巴巴
+關(guān)注
關(guān)注
7文章
1607瀏覽量
47059 -
應(yīng)用程序
+關(guān)注
關(guān)注
37文章
3237瀏覽量
57547
發(fā)布評論請先 登錄
相關(guān)推薦
評論