arthas學習圖文記錄

来源:https://www.cnblogs.com/pluto-charon/archive/2022/05/17/16281970.html
-Advertisement-
Play Games

Arthas 是阿裡開源的 Java 診斷工具。線上排查問題,無需重啟;動態跟蹤 Java 代碼;實時監控 JVM 狀態。Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。 Artha ...


Arthas 是阿裡開源的 Java 診斷工具。線上排查問題,無需重啟;動態跟蹤 Java 代碼;實時監控 JVM 狀態。Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。

Arthas可以通過簡單的命令交互模式,接入運行的JVM,快速定位和診斷線上程式運行的問題。在不重啟服務的情況下,實時,動態的修改相關代碼,並實時生效,具體工作原理如下:

  1. 連接JVM,通過attach機制,通過attach pid連接正在運行的JVM
  2. 查看及修改JVM位元組碼,通過instrument技術對運行中的JVM附加或修改位元組碼來實現增強的邏輯

Arthas的執行過程如下:Arthas底層調用rt.jar包的ManagementFactory獲取整個JVM內部信息,通過命令集成與後端交互,執行,返回結果,整個工程簡單清晰,容易上手。

arthas-demo入門

可以使用阿裡雲給的基礎教程地址練習: https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=arthas-basics

在這裡,我使用自己的伺服器,跟著基礎教程做入門聯繫。

1.下載math-game.jar,再用java -jar命令啟動

[root@localhost arthas]# wget https://arthas.aliyun.com/math-game.jar
[root@localhost arthas]# java -jar arthas-boot.jar

2.新開Terminal ,下載arthas-boot.jar,再用java -jar命令啟動

[root@localhost arthas]# wget https://arthas.aliyun.com/arthas-boot.jar
[root@localhost arthas]# java -jar arthas-boot.jar

arthas-bootArthas的啟動程式,它啟動後,會列出所有的Java進程,用戶可以選擇需要診斷的目標進程。

選擇第一個進程,輸入 1 (math-game這個程式對應的就是1),再Enter/回車

Attach成功之後,會列印Arthas LOGO。輸入 help 可以獲取到更多的幫助信息。

3. dashboard 命令可以查看當前系統的實時數據面板

數據說明:

  • ID:java級別的線程ID,註意這個ID不能跟jstack中的nativeID一一對應
  • NAME:線程名
  • GROUP:線程組名
  • PRIORI:線程的優先順序,1~10之間的數字,越大表示優先順序越高
  • STATE:線程的狀態
  • %CPU:線程的CPU使用率,比如採樣間隔1000ms,某個線程的增量cpu時間為100ms,則cpu的使用率為100/1000=10%
  • DELTA_TIME:上次採樣之後線程運行增量cpu時間,數據格式為秒
  • TIME:線程運行總CPU時間,數據格式為 分:秒
  • INTERRUPTED:線程當前的中斷位狀態
  • DAEMON:是否是daemon(後臺)線程

4. thread 命令會列印線程ID 1的棧

還可以通過thread 1 | grep 'main(' 命令來查找main class:

參數說明:

參數名稱 參數說明
id 線程id
[ n: ] 指定最忙的前N個線程並列印堆棧
[ b ] 找出當前阻塞其他線程的線程(目前只支持找出synchronized關鍵字阻塞住的線程, 如果是java.util.concurrent.Lock, 目前還不支持。)
[ i ] 指定cpu占比統計的採樣間隔,單位為毫秒
[ --all ] 顯示所有匹配的線程
[ --state ] 查看指定狀態的線程,如: thread --state WAITING

5. sc命令來查找JVM里已載入的類

sc為“Search-Class” 的簡寫,能搜索出所有已經載入到 JVM 中的 Class 信息。

參數說明:

參數名稱 參數說明
class-pattern 類名錶達式匹配,支持全限定名。如:demo.MathGame,也支持demo/MathGame
method-pattern 方法名錶達式匹配
[ d ] 輸出當前類的詳細信息,包括這個類所載入的原始文件來源,類的聲明,載入的ClassLoader等詳細信息;如果一個類被多個ClassLoader所載入,則會出現多次
[ E ] 開啟正則表達式匹配,預設為通配符匹配
[ f ] 輸出當前類的成員變數信息(需要配合參數 -d一起使用)
[ x: ] 指定輸出靜態變數時屬性的遍歷深度,預設為0,直接使用toString輸出
[ c: ] 指定class的ClassLoader的hashcode
[ classLoaderClass: ] 指定執行表達式的ClassLoader的class name
[ n: ] 具有詳細信息的匹配類的最大數量,預設為100

sm為“Search-Method” 的簡寫,查詢某個類下所有的方法,與sc的功能類似,這裡就不詳細介紹了。

6. jad命令來反編譯代碼

還可以反編譯指定的函數

反編譯時只顯示源代碼

預設情況下,反編譯結果里會帶有ClassLoader信息,通過--source-only選項,可以只列印源代碼。這樣就會清爽很多。

7. watch方法執行數據觀測

watch命令可以查看函數的參數/返回值/異常信息,通過編寫 OGNL 表達式進行對應變數的查看。

從上面的結果里,說明函數被執行了兩次,第一次結果是 location=AtExceptionExit,說明函數拋出了異常,因此returnObj是null;第二次結果是location=AtExit,說明函數正常返回,因此可以看到returnObj的結果是一個ArrayList。

參數說明:

參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
express 觀察表達式,預設值為:{params,target,returnObj},單個值可以不用加 {},多個值需要加
condition-express 條件表達式,不能加 {},可以使用逗號分隔子表達式,取表達式最後一個值來判斷
[ b ] 在方法調用之前觀察,預設關閉,由於觀察事件點是在方法調用前,此時返回值或異常均不存在,params代表方法入參
[ e ] 在方法異常之後觀察,預設關閉,params代表方法出參
[ s ] 在方法返回之後觀察,預設關閉,params代表方法出參
[ f ] 在方法結束之後(正常返回和異常返回)觀察,預設打開,params代表方法出參
[ E ] 開啟正則表達式匹配,預設為通配符匹配
[ x: ] 指定輸出結果的屬性遍歷深度,預設為1
[ #cost ] 監控耗時

條件表達式的例子:

下麵這個例子表示只有參數小於0的調用才會響應。

異常信息的例子:

-e 表示拋出異常時才觸發

express中,表示異常信息的變數時throwExp

8. vmtool命令,可以搜索記憶體對象

vmtool 利用JVMTI介面,實現查詢記憶體對象,強制GC等功能。

參數說明:

參數名稱 參數說明
--action getInstances 返回結果綁定到 instances變數上,它是數組。
--className 指定類名(完成路徑),支持 java.lang.String,也支持java/lang/String
[ --limit ] 限制返回值數量,避免獲取超大數據時對JVM造成壓力。預設值是10。
[ -x ] 指定返回結果展開層數,預設為1
[ c: ] 指定class的ClassLoader的hashcode(通過sc命令找到載入class的classLoader)
[ classLoaderClass: ] 指定執行表達式的ClassLoader的class name

強制GC的命令:vmtool --action forceGc

9. 退出Arthas

exit 或者 quit 命令可以退出Arthas。退出Arthas之後,還可以再次用 java -jar arthas-boot.jar 來連接。

10. 徹底退出Arthas

exit/quit命令只是退出當前session,arthas server還在目標進程中運行。

想完全退出Arthas,可以執行 stop 命令。

Arthas的其他重點使用功能

1. mc 記憶體編譯器(Memory Compiler/記憶體編譯器)

Memory Compiler/記憶體編譯器,編譯.java文件生成.class。通過 -c / --classLoaderClass 參數指定classLoader,-d 參數指定輸出目錄;編譯生成.class文件之後,可以結合retransform 命令實現熱更新代碼。retransform的限制:1.不允許新增加field和method 2.正在跑的函數,沒有退出不能生效

這裡還是使用arthas的提供的教程:https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=command-mc-retransform

1.由於正在跑的函數沒有退出時不生效的,所以上面的math-game的demo就不能使用了,所以得下載另一個demo(一個簡單的spring-boot應用)。

[root@localhost arthas]# wget https://raw.githubusercontent.com/hengyunabc/spring-boot-inside/master/demo-arthas-spring-boot/demo-arthas-spring-boot.jar
[root@localhost arthas]# java -jar demo-arthas-spring-boot.jar 

2.新開一個Terminal;訪問下麵這個路徑,可以看到報錯(500異常)了。

3.啟動arthas-boot應用。

4.反編譯代碼可以看到,當id小於1是,就會拋出異常。

在這裡,我們修改文件,想讓id小於1時還是能正常返回,不拋出異常。

5.jad反編譯UserController,將結果保存在/tmp/UserController.java文件夾里。

[arthas@1645]$ jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java

6.通過vim /tmp/UserController.java編輯java類。

7.通過sc查找載入UserContoller的ClassLoader,也可以在jad時顯示源碼,裡面也有classLoader的信息。

以下三個命令任意一個都可以。可以看到,這個java類是由LaunchedURLClassLoader@1be6f5c3 這個類載入器載入的。

8.通過mc命令編譯,同時指定--classLoaderClass參數指定ClassLoader:

[arthas@1645]$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp

也可以通過-c 參數指定ClassLoaderHash:

[arthas@1645]$ mc --c 1be6f5c3 /tmp/UserController.java -d /tmp

可以看到,在tmp文件夾下,根據UserController的類的全路徑編譯了一個class文件:

9.retransform 命令中西載入新編譯好的UserContoller.class類:

10.重新編譯文件可以看到,代碼已經替換成最新的了:

11.訪問:

顯示已經替換過的類:retransform -l

恢復修改前的代碼,清楚指定的類:retransform -d 1

清楚所有的:retransform --deleteAll

2.trace 方法內部調用路徑,並輸出方法路徑上的每個節點上耗時

可以觀察方法執行的時候哪個子調用比較慢

[arthas@1645]$ trace ClassName methodName

trace 命令能主動搜索 class-patternmethod-pattern 對應的方法調用路徑,渲染和統計整個調用鏈路上的所有性能開銷和追蹤調用鏈路。在進行性能調優的時候十分有效。

參數說明:

參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
express 觀察表達式,預設值為:{params,target,returnObj},單個值可以不用加 {},多個值需要加
condition-express 條件表達式
[ E ] 開啟正則表達式匹配,預設為通配符匹配
[ n: ] 命令執行次數
[ #cost ] 方法執行耗時
[ --skipJDKMethod ] 跳過jdk方法,預設為true

不跳過JDK方法:

只展示耗時大於1ms的調用路徑:

動態trace:

從上圖中可以看到,primeFactors的方法耗時最長,如果想深入primeFactors方法,可以打開一個新的終端,使用telnet localhost 3658 連接上arthas,在trace primeFactors時指定listenerId。

這時終端2列印的結果,說明已經增強了一個函數:Affect(class count: 1 , method count: 1),但不再列印更多的結果。

再查看終端1,可以發現trace的結果增加了一層,列印了primeFactors函數里的內容:

註意 --listenerId指定的id在前一條命令的輸出中可以看到。

3.stack 查看某個函數的調用堆棧路徑

很多時候,在一個方法被執行時,方法的執行路徑非常多,或者根本就不著調這個方法時從哪裡被執行的,就可以使用stack命令。此命令和trace命令結構類似。

[arthas@1645]$ stack demo.MathGame primeFactors

參數說明:

參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
express 觀察表達式,預設值為:{params,target,returnObj},單個值可以不用加 {},多個值需要加
condition-express 條件表達式
[ E ] 開啟正則表達式匹配,預設為通配符匹配
[ n: ] 命令執行次數

4.tt 命令

tt是TimeTunnel 的縮寫,tt命令記錄方法執行數據的時空隧道,記錄下指定方法每次調用的入參和返回信息,並能對這些不同的時間下調用進行觀測。

watch 雖然很方便和靈活,但需要提前想清楚觀察表達式的拼寫,這對排查問題而言要求太高,因為很多時候我們並不清楚問題出自於何方,只能靠蛛絲馬跡進行猜測。

這個時候如果能記錄下當時方法調用的所有入參和返回值、拋出的異常會對整個問題的思考與判斷非常有幫助。

參數說明:

參數名稱 參數說明
-t 記錄下類對應的方法的每次執行情況
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
[ n: ] 命令執行次數
condition-express 條件表達式

表格欄位說明:

表格欄位 欄位解釋
index 時間片段記錄編號,每一個編號代表著一次調用,後續tt還有很多命令都是基於此編號指定記錄操作,非常重要。
timestamp 方法執行的本機時間,記錄了這個時間片段所發生的本機時間
cost(ms) 方法執行的耗時
is-ret 方法是否以正常返回的形式結束
is-exp 方法是否以拋異常的形式結束
object 執行對象的hashCode(),註意,曾經有人誤認為是對象在JVM中的記憶體地址,但很遺憾他不是。但他能幫助你簡單的標記當前執行方法的類實體
class 執行的類名
method 執行的方法名

檢索調用記錄:

tt -l 檢索所有的調用記錄:

篩選出 primeFactors 方法的調用信息:

通過 -i 參數後邊跟著對應的 INDEX 編號查看到他的詳細信息:

重做一次調用:

tt 命令由於保存了當時調用的所有現場信息,所以我們可以自己主動對一個 INDEX 編號的時間片自主發起一次調用。此時需要使用 -p 參數。通過 --replay-times 指定 調用次數,通過 --replay-interval 指定多次調用間隔(單位ms, 預設1000ms)

需要強調的點

  1. ThreadLocal 信息丟失

    很多框架偷偷的將一些環境變數信息塞到了發起調用線程的 ThreadLocal 中,由於調用線程發生了變化,這些 ThreadLocal 線程信息無法通過 Arthas 保存,所以這些信息將會丟失。

  2. 引用的對象

    需要強調的是,tt 命令是將當前環境的對象引用保存起來,但僅僅也只能保存一個引用而已。如果方法內部對入參進行了變更,或者返回的對象經過了後續的處理,那麼在 tt 查看的時候將無法看到當時最準確的值。這也是為什麼 watch 命令存在的意義。

5.monitor 方法執行監控

對匹配的class-pattern / method-pattern的類、方法的調用進行監控。monitor命令是一個非實時返回的命令(並不是輸入之後立即返回,而是不斷的等待目標java進程返回信息)。

參數說明:

參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
[ E ] 開啟正則表達式匹配,預設為通配符匹配
[ c: ] 統計周期,預設值為120秒,是一個整型的參數值

監控項說明:

監控項 timestamp class method total success tail rt fail-rate
說明 時間戳 java類 方法 調用次數 成功次數 失敗次數 平均rt 失敗率

5.target-ip

target-ip 為指定綁定的IP,如果不指定IP,Arthas只listen 127.0.0.1,所以如果想從遠程連接,則可以使用 --target-ip參數指定listen的IP。

java -jar arthas-boot.jar --target-ip IP

綁定遠程訪問IP後,可以在通過telnet 或者http的方式遠程連接Arthas進行問題排查

還有更多的功能請查看arthas的官方文檔。

本文版權歸Charon和博客園共有,原創文章,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 當和朋友談到AOP時,第一映像會說AOP的應用層面,比如攔截器、過濾器,實現復用等等使用層面上。 這些應用層面上的回答遠遠沒有深入AOP的思想。是的,AOP是思想,面向切麵思想。 既然是編程思想,那我們就有必要瞭解AOP的整個過程,以及AOP思想出現的原因。 AOP面向切麵編程思想,能夠解決什麼問題 ...
  • Cron表達式的介紹: cron的表達式是被用來配置CronTrigger實例的。 cron的表達式是字元串,實際上是有七個子表達式,描述個別細節的時間表。 這些子表達式是由空格分開的,分別代表: Seconds Minutes Hours Day-of-Month Month Day-of-Wee ...
  • 我說util類就沒有加@Service註解的,只有static方法 他說不是吧 是這樣的嗎 他百度後說 好吧是這樣的 我真的無語....可是這真的是基礎常識啊,還有他到底怎麼理解service層呢? 能幹出這種事讓我不得不懷疑他到底有沒有學過springboot啊!99.999%的java項目都是用 ...
  • #運算符 JAVA語言支持入下運算符。 %:餘數 !=:不等於 &&:and ||:or !:not ##二元運算符 整數預設為int類型,按類型優先順序自動轉換,下圖說明瞭short加byte的值自動變成了int。 關係運算符返回的結果必然是布爾值 ##一元運算符 自增,自減及冪運算 a++--為先 ...
  • 一、問題背景 前情提要(第5.8章節): 【Python可視化大屏】全流程揭秘實現可視化數據大屏的背後原理! 在用Page函數拖拽組合完大屏時,點擊頁面左上角的Save Config,會生成一個文件:chart_config.json 這個文件是什麼?有什麼作用?怎麼高效利用它? 二、揭開json文 ...
  • 跟著尚矽谷做了尚醫通項目來學習,原本以為知識點並不是很多,面試後發現如果深挖,有很多需要學習理解的點,此系列博客記錄項目中涉及的知識點,也希望能幫助到做了同一個項目的同學。博客中的知識點都是自己搜集資料總結,如有錯誤歡迎指出! 此項目使用Spring Cloud技術棧,各個微服務站點基於Spring ...
  • 大家好,這篇文章分享了C程式設計(譚浩強)第五版第六章課後題答案,所有程式已經測試能夠正常運行,如果小伙伴發現有錯誤的的地方,歡迎留言告訴我,我會及時改正!感謝大家的觀看!!! ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...