快速上手Alibaba Arthas


點擊返回上層目錄

原創聲明:作者:Arnold.zhao 博客園地址:https://www.cnblogs.com/zh94

Arthas

本文主要聚焦於快速上手並使用Arthas,所以對於基本的概念及使用目的此處不再贅述,詳情可參考如下鏈接

關於Arthas的基本概念可參考:

https://github.com/alibaba/arthas/blob/master/README_CN.md

關於Arthas等相關JVM Debug工具的實現原理可參考:

https://www.cnblogs.com/meituantech/p/11670535.html

https://blog.csdn.net/u010862794/article/details/87773434

快速使用

啟動Arthas

$ $ curl -O https://alibaba.github.io/arthas/arthas-demo.jar
$ $ java -jar arthas-boot.jar
* [1]: 35542
  [2]: 71560 arthas-demo.jar
  1
  此處選擇序號來表示當前所要鏈接的進程;

dashboard

介紹:輸入dashboard,按回車/enter,會展示當前進程的信息,按ctrl+c可以中斷執行。

優勢:當在生產環境中我們需要查看當前進程內線程的運行情況時需要使用Linux原生的 top -p PID -H來獲取線程信息;當需要查看進程的GC情況時,則需要使用jstat 或 jconsole等工具來監控內存的變化;而此處dashboard控制台一鍵集成,想要實時觀察GC和線程信息則再也不用連續的觀察多個面板了;

thread

介紹:通過使用dashboard獲取到當前所有的線程運行信息后,使用thread 1打印當前ID為1的線程棧信息

優勢:當生產環境一個線程CPU飆高,或者鎖死的情況時,我們常規的做法是 jstack 快速打印當前進程的線程堆棧信息,然后再具體分析對應的堆棧日志來依次觀察具體的問題點;而此處當我們使用dashboard捕獲到具體的異常線程時,直接使用Arthas 的thread命令便可以直接打印當前指定線程的棧信息,快速定位具體哪塊方法體所引起的問題;

[arthas@23846]$ thread 1
"main" Id=1 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at demo.MathGame.main(MathGame.java:17)

sc

介紹:查看當前JVM中所加載的類信息,此處表示查看當前MatchGame類的具體信息(支持正則匹配)

優勢:通過使用sc命令可以排查你當前項目中的某些類是否被加載進來,或者在Spring中某些依賴是否被正確加載等問題

[arthas@23846]$ sc -d *MathGame		(-d表示查看detail詳情,關於當前sc命令的options參數,可以使用 sc -h 獲取具體的參數格式)
 class-info        demo.MathGame (表示當前類的包路徑信息)
 code-source       /opt/shengheApp/arthas/arthas-demo.jar(當前類加載自那個jar包中)
 name              demo.MathGame	
 isInterface       false		 (是否是接口)
 isAnnotation      false		(是否是注解)
 isEnum            false		(是否是枚舉等等)
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       MathGame		(類簡稱)
 modifier          public	(當前類的訪問修飾符)
 annotation
 interfaces
 super-class       +-java.lang.Object	(當前類的父類)
 class-loader      +-sun.misc.Launcher$AppClassLoader@70dea4e(當前類加載自那個ClassLoader)
                     +-sun.misc.Launcher$ExtClassLoader@708ab80c
 classLoaderHash   70dea4e
Affect(row-cnt:1) cost in 7 ms.

jad

介紹:使用jad來反編譯代碼,類似於我們桌面端常用的 jd-gui等工具

優勢:生產環境更新代碼后,很可能會出現代碼更新后不生效等問題(比如本地代碼打包未重新編譯等),通過使用jad反編譯代碼后,可以快速確認當前線上代碼是否是本地的最新代碼等問題;並且jad反編譯后的代碼可讀性更強,相比於jdk自帶的javap反編譯命令要好很多

[arthas@23846]$ jad demo.MathGame

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@70dea4e
  +-sun.misc.Launcher$ExtClassLoader@708ab80c
Location:
/opt/shengheApp/arthas/arthas-demo.jar
/*
 * Decompiled with CFR.
 */
package demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class MathGame {
    private static Random random = new Random();
    public int illegalArgumentCount = 0;
 	public List<Integer> primeFactors(int number) {
        if (number < 2) {
            ++this.illegalArgumentCount;
            throw new IllegalArgumentException("number is: " + number + ", need >= 2");
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        int i = 2;
        while (i <= number) {
            if (number % i == 0) {
                result.add(i);
                number /= i;
                i = 2;
                continue;
            }
            ++i;
        }
        return result;
    }

原創聲明:作者:Arnold.zhao 博客園地址:https://www.cnblogs.com/zh94

watch(重要)

通過字節碼增強技術來實現的,會在指定類的方法中插入一些切面來實現數據統計和觀測,因此在線上、預發使用時,請盡量明確需要觀測的類、方法以及條件,診斷結束要執行 stop 或將增強過的類執行 reset 命令。

介紹:方法執行數據觀測,可以輕松的觀察到當前指定方法的調用情況以及通過書寫特定的OGNL表達式來進行對應變量的查看,能觀察到的范圍為當前方法的:返回值、拋出異常、入參

關於OGNL表達式的說明可參考:

官網:https://commons.apache.org/proper/commons-ognl/language-guide.html

博客:https://cloud.tencent.com/developer/article/1554323

重要說明:

  • 當前watch的命令實際上只是給當前所要被觀察的方法增加一個切面的代碼來實現后續的統計;

  • 而我們通過切面則可以捕獲到當前被執行方法的以下參數:如方法的入參是什么?方法的出參是什么?方法的執行結果是否拋出異常,拋出的異常棧是什么等信息;

  • 那么這些所有被捕獲到的觀察信息,實際上都被封裝到了一個通用的通知對象Advice的類中,當前Advice類的屬性及包含了方法的入參,也包含了方法的出參等數據

  • 而我們所書寫的OGNL表達式,實際上就是針對於當前的Advice的類屬性而寫,比如此時OGNL表達式寫的是:{params,returnObj} ,那么此OGNL所表示的含義則是輸出當前被觀察類的入參(params),和返回結果(returnObj)的內容;

關於當前Advice通知類的具體參數都有哪些,可以參考該鏈接:https://arthas.gitee.io/advice-class.html

watch命令格式如下:

參數名稱 參數說明
class-pattern 類名表達式匹配
method-pattern 方法名表達式匹配
express 觀察表達式(OGNL)
condition-express 條件表達式
-b 在方法調用之前觀察
-e 在方法異常之后觀察
-s 在方法返回之后觀察
-f 在方法結束之后(正常返回和異常返回)觀察
-E 開啟正則表達式匹配,默認為通配符匹配
-x value 輸出結果的屬性遍歷深度,默認為 1

優勢:想要調試某個線上服務的偶發性BUG,但是又不能重啟線上服務的情況下,通過對當前所需監控的方法以及各個被調用的嵌套方法都增加watch監控的方式以此來實現動態DEBUG的效果

劣勢:不可以在指定的代碼行增加動態代碼的方式來達到DEBUG的效果;BTrace可以實現更佳的服務器線上DEBUG效果,但使用方式相對更加重一些

執行命令解讀:
watch demo.MathGame【指定類路徑】 primeFactors【指定被觀察方法名】 "{params,returnObj}"【指定OGNL表達式】 "params[0]<0" 【條件表達式,表示當前入參<0時則觸發檢測】 -x 3【指定輸出結果的遍歷深度】 -f【表示在方法結束之后觸發觀察】

[arthas@23846]$ watch demo.MathGame primeFactors "{params,returnObj}" "params[0]<0"  -x 3 -f
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 36 ms.
ts=2020-04-29 15:47:59; [cost=0.197494ms] result=@ArrayList[
    @Object[][
        @Integer[-56580],			(當前被觀察方法的入參)
    ],
    null,							(當前被觀察方法的出參)
]
ts=2020-04-29 15:48:03; [cost=0.073761ms] result=@ArrayList[
    @Object[][
        @Integer[-161310],			(當前被觀察方法的入參)
    ],
    null,							(當前被觀察方法的出參)
]

由於我們上面執行命令時設置的條件表達式是只針對 入參 < 0 的執行方法才進行輸出,所以以上兩個輸出的結果全部是入參為負數時的數據

reset

介紹:用於還原指定的增強類,使用watch等命令對指定的方法進行了相關debug診斷完以后,則需要使用reset進行類的還原

還原指定類:
[arthas@23846]$ reset demo.MathGame
Affect(class-cnt:0 , method-cnt:0) cost in 0 ms.

還原所有類:
[arthas@23846]$ reset
Affect(class-cnt:0 , method-cnt:0) cost in 1 ms.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM