Arthas详解
文章目錄
- 概述
- 安裝
- 快速安裝
- 使用`arthas-boot`(官網(wǎng)推薦)
- 使用`as.sh`
- 全量安裝
- 把Arthas安裝到基礎(chǔ)鏡像里
- 卸載
- 使用
- 命令詳解
- 基礎(chǔ)命令
- help
- cat
- echo
- grep
- base64
- tee
- pwd
- cls
- version
- history
- keymap
- 后臺異步命令相關(guān)快捷鍵
- 會話相關(guān)
- quit
- stop
- session
- reset
- jvm相關(guān)
- dashboard
- thread
- jvm
- sysprop
- sysenv
- vmoption
- perfcounter
- logger
- getstatic
- ognl
- mbean
- heapdump
- vmtool
- class/classloader相關(guān)
- sc (search class)
- sm (search method)
- jad
- mc
- retransform
- 顯式觸發(fā) retransform
- 消除 retransform 的影響
- 結(jié)合 jad/mc 命令使用
- 上傳 .class 文件到服務(wù)器的技巧
- retransform的限制
- redefine
- dump
- classloader
- 示例
- monitor/watch/trace相關(guān)
- monitor
- 監(jiān)控的維度說明
- 參數(shù)說明
- watch
- 參數(shù)說明
- 表達式
- 表達式核心變量
- **示例**
- trace
- 參數(shù)說明
- 示例
- stack
- tt (Time Tunnel)
- 參數(shù)說明
- 表格字段說明
- 條件表達式
- 檢索調(diào)用記錄
- replay
- 調(diào)用方法
- 需要強調(diào)的點
- 示例
- profiler/火焰圖
- profiler
- 參數(shù)說明
- action 示例
- action list
- event list
- execute命令格式
- 火焰圖的理解
- 鑒權(quán)
- auth
- options
- options
- 后臺異步任務(wù)
- 其他
- logger
- mbean
- 實戰(zhàn)
- 參考
- profiler問題
- javax.management.ObjectName
概述
安裝
快速安裝
使用arthas-boot(官網(wǎng)推薦)
下載arthas-boot.jar,然后用java -jar的方式啟動:
curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar如果下載速度比較慢,可以使用aliyun的鏡像:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http雖然這種方式簡單,但是對不能連接外網(wǎng)的不友好。
使用as.sh
Arthas 支持在 Linux/Unix/Mac 等平臺上一鍵安裝,請復(fù)制以下內(nèi)容,并粘貼到命令行中,敲 回車 執(zhí)行即可:
curl -L https://arthas.aliyun.com/install.sh | sh上述命令會下載啟動腳本文件 as.sh 到當(dāng)前目錄,你可以放在任何地方或?qū)⑵浼尤氲?$PATH 中。
直接在shell下面執(zhí)行./as.sh,就會進入交互界面。
也可以執(zhí)行./as.sh -h來獲取更多參數(shù)信息。
全量安裝
最新版本,點擊下載:https://arthas.aliyun.com/download/latest_version?mirror=aliyun
解壓后,在文件夾里有arthas-boot.jar,直接用java -jar的方式啟動:
java -jar arthas-boot.jar把Arthas安裝到基礎(chǔ)鏡像里
可以很簡單把Arthas安裝到你的Docker鏡像里。
FROM openjdk:8-jdk-alpine# copy arthas COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas如果想指定版本,可以查看具體的tags:
https://hub.docker.com/r/hengyunabc/arthas/tags
卸載
-
在 Linux/Unix/Mac 平臺
刪除下面文件:
rm -rf ~/.arthas/ rm -rf ~/logs/arthas -
Windows平臺直接刪除user home下面的.arthas和logs/arthas目錄
使用
1、啟動Arthas
$ $ java -jar arthas-boot.jar * [1]: 35542[2]: 71560 math-game.jar2、選擇應(yīng)用java進程:
如果第一次使用,會從官網(wǎng)下載一些jar包。
$ $ java -jar arthas-boot.jar * [1]: 35542[2]: 71560 math-game.jar1[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.5.3?mirror=aliyun [INFO] File size: 12.72 MB, downloaded size: 1.91 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 4.06 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 5.73 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 7.36 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 8.52 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 9.67 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 10.77 MB, downloading ... [INFO] File size: 12.72 MB, downloaded size: 11.86 MB, downloading ... [INFO] Download arthas success. [INFO] arthas home: /root/.arthas/lib/3.5.3/arthas [INFO] Try to attach process 8 [INFO] Attach process 8 success. [INFO] arthas-client connect 127.0.0.1 3658,---. ,------. ,--------.,--. ,--. ,---. ,---. / O \ | .--. ''--. .--'| '--' | / O \ ' .-' | .-. || '--'.' | | | .--. || .-. |`. `-. | | | || |\ \ | | | | | || | | |.-' | `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' wiki https://arthas.aliyun.com/doc tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html version 3.5.3 main_class pid 8 time 2021-07-27 19:24:26命令詳解
基礎(chǔ)命令
help
查看命令幫助信息
cat
打印文件內(nèi)容,和linux里的cat命令類似
echo
打印參數(shù),和linux里的echo命令類似
grep
匹配查找,和linux里的grep命令類似
base64
base64編碼轉(zhuǎn)換,和linux里的base64命令類似。
只能對文件進行加解密。
USAGE: base64 [-d] [-h] [-i <value>] [-o <value>] [-M <value>] [file] SUMMARY: Encode and decode using Base64 representation EXAMPLES: base64 /tmp/test.txt base64 --input /tmp/test.txt --output /tmp/result.txt base64 -d /tmp/result.txttee
復(fù)制標(biāo)準(zhǔn)輸入到標(biāo)準(zhǔn)輸出和指定的文件,和linux里的tee命令類似
pwd
返回當(dāng)前的工作目錄,和linux命令類似
cls
清空當(dāng)前屏幕區(qū)域
version
輸出當(dāng)前目標(biāo) Java 進程所加載的 Arthas 版本號
history
打印命令歷史
keymap
Arthas快捷鍵列表及自定義快捷鍵
keymap命令輸出當(dāng)前的快捷鍵映射表:
默認的快捷鍵如下:
| "\C-a" | ctrl + a | beginning-of-line | 跳到行首 |
| "\C-e" | ctrl + e | end-of-line | 跳到行尾 |
| "\C-f" | ctrl + f | forward-word | 向前移動一個單詞 |
| "\C-b" | ctrl + b | backward-word | 向后移動一個單詞 |
| "\e[D" | 鍵盤左方向鍵 | backward-char | 光標(biāo)向前移動一個字符 |
| "\e[C" | 鍵盤右方向鍵 | forward-char | 光標(biāo)向后移動一個字符 |
| "\e[B" | 鍵盤下方向鍵 | next-history | 下翻顯示下一個命令 |
| "\e[A" | 鍵盤上方向鍵 | previous-history | 上翻顯示上一個命令 |
| "\C-h" | ctrl + h | backward-delete-char | 向后刪除一個字符 |
| "\C-?" | ctrl + shift + / | backward-delete-char | 向后刪除一個字符 |
| "\C-u" | ctrl + u | undo | 撤銷上一個命令,相當(dāng)于清空當(dāng)前行 |
| "\C-d" | ctrl + d | delete-char | 刪除當(dāng)前光標(biāo)所在字符 |
| "\C-k" | ctrl + k | kill-line | 刪除當(dāng)前光標(biāo)到行尾的所有字符 |
| "\C-i" | ctrl + i | complete | 自動補全,相當(dāng)于敲TAB |
| "\C-j" | ctrl + j | accept-line | 結(jié)束當(dāng)前行,相當(dāng)于敲回車 |
| "\C-m" | ctrl + m | accept-line | 結(jié)束當(dāng)前行,相當(dāng)于敲回車 |
| "\C-w" | backward-delete-word | ||
| "\C-x\e[3~" | backward-kill-line | ||
| "\e\C-?" | backward-kill-word |
- 任何時候 tab 鍵,會根據(jù)當(dāng)前的輸入給出提示
- 命令后敲 - 或 -- ,然后按 tab 鍵,可以展示出此命令具體的選項
后臺異步命令相關(guān)快捷鍵
- ctrl + c: 終止當(dāng)前命令
- ctrl + z: 掛起當(dāng)前命令,后續(xù)可以 bg/fg 重新支持此命令,或 kill 掉
- ctrl + a: 回到行首
- ctrl + e: 回到行尾
會話相關(guān)
quit
退出當(dāng)前 Arthas 客戶端,其他 Arthas 客戶端不受影響
stop
關(guān)閉 Arthas 服務(wù)端,所有 Arthas 客戶端全部退出。
如果是在一臺機器上打開多個terminal,則就是多個客戶端。本機就是服務(wù)器。
session
查看當(dāng)前會話的信息
[arthas@8]$ sessionName Value -------------------------------------------------- JAVA_PID 8 SESSION_ID 2f33d907-bc92-455e-995f-f5b70291c065reset
重置增強類,將被 Arthas 增強過的類全部還原,Arthas 服務(wù)端關(guān)閉時會重置所有增強過的類
jvm相關(guān)
dashboard
當(dāng)前系統(tǒng)的實時數(shù)據(jù)面板
按ctrl+c可以中斷執(zhí)行,或者輸入 q
thread
查看當(dāng)前 JVM 的線程堆棧信息
USAGE: thread [--all] [-h] [-b] [--lockedMonitors] [--lockedSynchronizers] [-i <value>] [--state <value>] [-n <value>] [id]EXAMPLES: thread thread 51 thread -n -1 thread -n 5 thread -b thread -i 2000 thread --state BLOCKED WIKI: https://arthas.aliyun.com/doc/thread OPTIONS: --all Display all thread results instead of the first pag e -h, --help this help -b, --include-blocking-thread Find the thread who is holding a lock that blocks the most number of threads. --lockedMonitors Find the thread info with lockedMonitors flag, default value is false. --lockedSynchronizers Find the thread info with lockedSynchronizers flag,default value is false. -i, --sample-interval <value> Specify the sampling interval (in ms) when calculating cpu usage. --state <value> Display the thead filter by the state. NEW, RUNNABLE, TIMED_WAITING, WAITING, BLOCKED, TERMINATED is optional. -n, --top-n-threads <value> The number of thread(s) to show, ordered by cpu utilization, -1 to show all. <id> Show thread stack示例:
jvm
查看當(dāng)前 JVM 的信息。會顯示很多段信息。
- RUNTIME:運行時信息
- CLASS-LOADING:類加載信息
- COMPILATION:編譯信息
- GARBAGE-COLLECTORS:GC
- MEMORY-MANAGERS:
- MEMORY:
- OPERATING-SYSTEM:
- THREAD:
- FILE-DESCRIPTOR:
sysprop
查看和修改JVM的系統(tǒng)屬性。可以通過tab補全。
USAGE: sysprop [-h] [property-name] [property-value] SUMMARY: Display, and change the system properties. EXAMPLES: sysprop sysprop file.encoding sysprop production.mode truesysenv
查看JVM的環(huán)境變量。SHELL等定義的變量。
USAGE: sysenv [-h] [env-name] KEY VALUE ---------------------------------------------------------------------------------- PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/u..... SW_SERVICES .... TZ Asia/Shanghai JAVA_HOME /usr/lib/jvm/java-1.8-openjdk EVN-ACTIVE release JAVA_OPTS -Xms1024m -Xmx2048m -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC LANG C.UTF-8 TRACK -javaagent:/opt/agent/skywalking-agent.jar APP_JAR app.jar HOSTNAME ... JAVA_ALPINE_VERSION 8.212.04-r0 LD_LIBRARY_PATH /usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/serve..... DEBUG_PORT 9052 SW_NS data SW_ENABLED true NACOS-NS 2ad71f49-ba5b-4a82-a4bf-05849aedc3ff PWD /cloudvmoption
查看和修改JVM里診斷相關(guān)的option
USAGE:vmoption [-h] [name] [value]Examples:vmoptionvmoption PrintGCvmoption PrintGC truevmoption PrintGCDetails trueKEY VALUE ORIGIN WRITEABLE ---------------------------------------------------------------------------------HeapDumpBeforeFullGC false DEFAULT trueHeapDumpAfterFullGC false DEFAULT trueHeapDumpOnOutOfMemoryError false DEFAULT trueHeapDumpPath DEFAULT trueCMSAbortablePrecleanWaitMillis 100 DEFAULT trueCMSWaitDuration 2000 DEFAULT trueCMSTriggerInterval -1 DEFAULT truePrintGC false DEFAULT truePrintGCDetails false DEFAULT truePrintGCDateStamps false DEFAULT truePrintGCTimeStamps false DEFAULT truePrintGCID false DEFAULT truePrintClassHistogramBeforeFullGC false DEFAULT truePrintClassHistogramAfterFullGC false DEFAULT truePrintClassHistogram false DEFAULT trueMinHeapFreeRatio 40 DEFAULT trueMaxHeapFreeRatio 70 DEFAULT truePrintConcurrentLocks false DEFAULT trueperfcounter
查看當(dāng)前 JVM 的Perf Counter信息
USAGE: perfcounter [-d] [-h] OPTIONS: -d, --details print all perf counter details -h, --help this helplogger
查看和修改logger
getstatic
查看類的靜態(tài)屬性。更好的替代方法是 ognl 命令
USAGE:getstatic [-c <value>] [--classLoaderClass <value>] [-x <value>] [-h] [-E] class-pattern field-pattern [express]SUMMARY:Show the static field of a classEXAMPLES:getstatic demo.MathGame randomgetstatic -c 39eb305e org.apache.log4j.LogManager DEFAULT_CONFIGURATION_FILEWIKI:https://arthas.aliyun.com/doc/getstaticOPTIONS:-c, --classloader <value> classLoader的hashcode,動態(tài)變化的--classLoaderClass <value> classLoader的類名(fullname).-x, --expand <value> 對象的展開層次,就展示多少層的屬性 (1 by default)-h, --help this help-E, --regex Enable regular expression to match (wildcard matching by default)<class-pattern> Class name pattern, use either '.' or '/' as separator<field-pattern> Field name pattern<express> the content you want to watch, written by ognl注: 這里classLoaderClass 在 java 8 是 sun.misc.Launcher$AppClassLoader,而java 11的classloader是jdk.internal.loader.ClassLoaders$AppClassLoader
hashcode是變化的,需要先查看當(dāng)前的ClassLoader信息,使用sc -d <ClassName>提取對應(yīng)ClassLoader的hashcode。
ognl
執(zhí)行ognl表達式
USAGE: ognl [-c <value>] [--classLoaderClass <value>] [-x <value>] [-h] expressEXAMPLES: ognl '@java.lang.System@out.println("hello")' ognl -x 2 '@Singleton@getInstance()' ognl '@Demo@staticFiled' ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}' ognl -c 5d113a51 '@com.taobao.arthas.core.GlobalOptions@isDump'mbean
查看 Mbean 的信息
heapdump
dump java heap, 類似jmap命令的heap dump功能
vmtool
從jvm里查詢對象,執(zhí)行forceGc
class/classloader相關(guān)
sc (search class)
查看JVM已加載的類信息
USAGE:sc [-c <value>] [--classLoaderClass <value>] [-d] [-x <value>] [-f] [-h] [-n <value>] [-E] class-patternSUMMARY:Search all the classes loaded by JVMEXAMPLES:sc -d org.apache.commons.lang.StringUtilssc -d org/apache/commons/lang/StringUtilssc -d *StringUtilssc -d -f org.apache.commons.lang.StringUtilssc -E org\\.apache\\.commons\\.lang\\.StringUtils參數(shù):
| class-pattern | 類名表達式匹配 |
| method-pattern | 方法名表達式匹配 |
| d | 輸出當(dāng)前類的詳細信息,包括這個類所加載的原始文件來源、類的聲明、加載的ClassLoader等詳細信息。 如果一個類被多個ClassLoader所加載,則會出現(xiàn)多次 |
| E | 開啟正則表達式匹配,默認為通配符匹配 |
| f | 輸出當(dāng)前類的成員變量信息(需要配合參數(shù)-d一起使用) |
| x | 指定輸出靜態(tài)變量時屬性的遍歷深度,默認為 0,即直接使用 toString 輸出 |
| c | 指定class的 ClassLoader 的 hashcode |
| classLoaderClass | 指定執(zhí)行表達式的 ClassLoader 的 class name |
| n | 具有詳細信息的匹配類的最大數(shù)量(默認為100) |
class-pattern支持全限定名,如com.taobao.test.AAA,也支持com/taobao/test/AAA這樣的格式,這樣,我們從異常堆棧里面把類名拷貝過來的時候,不需要在手動把/替換為.啦。
sc 默認開啟了子類匹配功能,也就是說所有當(dāng)前類的子類也會被搜索出來,想要精確的匹配,請打開options disable-sub-class true開關(guān)
sm (search method)
查看已加載類的方法信息。sm 命令只能看到由當(dāng)前類所聲明 (declaring) 的方法,父類則無法看到。
#與sc 命令類似 USAGE: sm [-c <value>] [--classLoaderClass <value>] [-d] [-h] [-n <value>] [-E] class-pattern [method-pattern]| class-pattern | 類名表達式匹配 |
| method-pattern | 方法名表達式匹配 |
| d | 展示每個方法的詳細信息 |
| E | 開啟正則表達式匹配,默認為通配符匹配 |
| c | 指定class的 ClassLoader 的 hashcode |
| classLoaderClass | 指定執(zhí)行表達式的 ClassLoader 的 class name |
| n | 具有詳細信息的匹配類的最大數(shù)量(默認為100) |
jad
反編譯指定已加載類的源碼,
USAGE: jad [--classLoaderClass <value>] [-c <value>] [-h] [--hideUnicode] [--lineNumber <value>] [-E] [--source-only] class-pattern [method-name] OPTIONS:--classLoaderClass <value> -c, --code <value> -h, --help this help--hideUnicode hide unicode, default value false--lineNumber <value> 是否包含行號,默認true-E, --regex 開啟正則表達式匹配,默認為通配符匹配--source-only 默認情況下,反編譯結(jié)果里會帶有ClassLoader信息,通過--source-only選項,可以只打印源代碼<class-pattern> Class name pattern, use either '.' or '/' as separator<method-name> method name pattern, decompile a specific method instead of the whole class # jad java.lang.String ClassLoader: Location:/** Decompiled with CFR.*/package java.lang;import java.io.ObjectStreamField;import java.io.Serializable;mc
Memory Compiler/內(nèi)存編譯器,編譯.java文件生成.class。
USAGE:mc [-c <value>] [--classLoaderClass <value>] [-d <value>] [--encoding <value>] [-h] sourcefiles...EXAMPLES:mc /tmp/Test.javamc -c 327a647b /tmp/Test.javamc -d /tmp/output /tmp/ClassA.java /tmp/ClassB.javaWIKI:https://arthas.aliyun.com/doc/mcOPTIONS:-c, --classloader <value> The hash code of the special ClassLoader--classLoaderClass <value> The class name of the special class's classLoader.-d, --directory <value> Sets the destination directory for class files--encoding <value> Source file encoding-h, --help this help<sourcefiles> source files編譯生成.class文件之后,可以結(jié)合retransform命令實現(xiàn)熱更新代碼。
注意,mc命令有可能失敗。如果編譯失敗可以在本地編譯好.class文件,再上傳到服務(wù)器。具體參考retransform命令說明。
retransform
加載外部的.class文件,retransform到JVM里
加載指定的 .class 文件,然后解析出class name,再retransform jvm中已加載的對應(yīng)的類。每加載一個 .class 文件,則會記錄一個 retransform entry.
如果多次執(zhí)行 retransform 加載同一個 class 文件,則會有多條 retransform entry.
顯式觸發(fā) retransform
$ retransform --classPattern demo.MathGame retransform success, size: 1, classes: demo.MathGame#顯示所有 retransform -l Id ClassName TransformCount LoaderHash LoaderClassName注意:對于同一個類,當(dāng)存在多個 retransform entry時,如果顯式觸發(fā) retransform ,則最后添加的entry生效(id最大的)。
消除 retransform 的影響
如果對某個類執(zhí)行 retransform 之后,想消除影響,則需要:
- 刪除這個類對應(yīng)的 retransform entry
- 重新觸發(fā) retransform
如果不清除掉所有的 retransform entry,并重新觸發(fā) retransform ,則arthas stop時,retransform過的類仍然生效。
結(jié)合 jad/mc 命令使用
- jad命令反編譯,然后可以用其它編譯器,比如vim來修改源碼
- mc命令來內(nèi)存編譯修改過的代碼
- 用retransform命令加載新的字節(jié)碼
上傳 .class 文件到服務(wù)器的技巧
使用mc命令來編譯jad的反編譯的代碼有可能失敗。可以在本地修改代碼,編譯好后再上傳到服務(wù)器上。有的服務(wù)器不允許直接上傳文件,可以使用base64命令來繞過。
在本地先轉(zhuǎn)換.class文件為base64,再保存為result.txt
base64 < Test.class > result.txt到服務(wù)器上,新建并編輯result.txt,復(fù)制本地的內(nèi)容,粘貼再保存
把服務(wù)器上的 result.txt還原為.class
base64 -d < result.txt > Test.class用md5命令計算哈希值,校驗是否一致
retransform的限制
-
不允許新增加field/method
-
正在跑的函數(shù),沒有退出不能生效,比如下面新增加的System.out.println,只有run()函數(shù)里的會生效
public class MathGame {public static void main(String[] args) throws InterruptedException {MathGame game = new MathGame();while (true) {game.run();TimeUnit.SECONDS.sleep(1);// 這個不生效,因為代碼一直跑在 while里System.out.println("in loop");}}public void run() throws InterruptedException {// 這個生效,因為run()函數(shù)每次都可以完整結(jié)束System.out.println("call run()");try {int number = random.nextInt();List<Integer> primeFactors = primeFactors(number);print(number, primeFactors);} catch (Exception e) {System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());}}
redefine
加載外部的.class文件,redefine到JVM里
推薦使用 retransform 命令
- redefine的class不能修改、添加、刪除類的field和method,包括方法參數(shù)、方法名稱及返回值
- 如果mc失敗,可以在本地開發(fā)環(huán)境編譯好class文件,上傳到目標(biāo)系統(tǒng),使用redefine熱加載class
- 目前redefine 和watch/trace/jad/tt等命令沖突,以后重新實現(xiàn)redefine功能會解決此問題
注意, redefine后的原來的類不能恢復(fù),redefine有可能失敗(比如增加了新的field),參考jdk本身的文檔。
reset命令對redefine的類無效。如果想重置,需要redefine原始的字節(jié)碼。
redefine命令和jad/watch/trace/monitor/tt等命令會沖突。執(zhí)行完redefine之后,如果再執(zhí)行上面提到的命令,則會把redefine的字節(jié)碼重置。 原因是jdk本身redefine和Retransform是不同的機制,同時使用兩種機制來更新字節(jié)碼,只有最后修改的會生效。
dump
dump 已加載類的 byte code 到特定目錄。
USAGE: dump [--classLoaderClass <value>] [-c <value>] [-d <value>] [-h] [-l <value>] [-E] class-patternclassloader
查看classloader的繼承樹,urls,類加載信息,使用classloader去getResource
USAGE: classloader [-a] [-c <value>] [--classLoaderClass <value>] [-h] [-i] [-l] [--load <value>] [-r <value>] [-t]| l | 按類加載實例進行統(tǒng)計 |
| t | 打印所有ClassLoader的繼承樹 |
| a | 列出所有ClassLoader加載的類,請謹慎使用 |
| [c:] | ClassLoader的hashcode |
| [classLoaderClass:] | 指定執(zhí)行表達式的 ClassLoader 的 class name |
| [c: r:] | 用ClassLoader去查找resource |
| [c: load:] | 用ClassLoader去加載指定的類 |
示例
[arthas@8]$ classloadername numberOfInstances loadedCountTotalorg.springframework.boot.loader.LaunchedURLClassLoader 1 19217BootstrapClassLoader 1 4183sun.misc.Launcher$AppClassLoader 1 3275com.taobao.arthas.agent.ArthasClassloader 1 2436sun.reflect.DelegatingClassLoader 1025 1025org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader 2 386sun.misc.Launcher$ExtClassLoader 1 90com.alibaba.fastjson.util.ASMClassLoader 2 4 Affect(row-cnt:8) cost in 58 ms. [arthas@8]$ classloader -lname loadedCount hash parentBootstrapClassLoader 4183 null nullcom.alibaba.fastjson.util.ASMClassLoader@40ff5477 2 40ff5477 org.springframework.boot.loader.LaunchedURLClassLoader@62452cc9com.alibaba.fastjson.util.ASMClassLoader@38a77e1b 2 38a77e1b org.springframework.boot.loader.LaunchedURLClassLoader@62452cc9com.taobao.arthas.agent.ArthasClassloader@41e41a92 2439 41e41a92 sun.misc.Launcher$ExtClassLoader@8cd2bb5org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader@7e269af6 76 7e269af6 org.springframework.boot.loader.LaunchedURLClassLoader@62452cc9org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader@16b4a017 310 16b4a017 sun.misc.Launcher$AppClassLoader@18b4aac2org.springframework.boot.loader.LaunchedURLClassLoader@62452cc9 19217 62452cc9 sun.misc.Launcher$AppClassLoader@18b4aac2sun.misc.Launcher$AppClassLoader@18b4aac2 3275 18b4aac2 sun.misc.Launcher$ExtClassLoader@8cd2bb5sun.misc.Launcher$ExtClassLoader@8cd2bb5 90 8cd2bb5 null [arthas@8]$ classloader -t +-BootstrapClassLoader +-sun.misc.Launcher$ExtClassLoader@8cd2bb5+-com.taobao.arthas.agent.ArthasClassloader@41e41a92+-sun.misc.Launcher$AppClassLoader@18b4aac2+-org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader@16b4a017+-org.springframework.boot.loader.LaunchedURLClassLoader@62452cc9+-com.alibaba.fastjson.util.ASMClassLoader@40ff5477+-com.alibaba.fastjson.util.ASMClassLoader@38a77e1b+-org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader@7e269af6 Affect(row-cnt:9) cost in 14 ms. [arthas@8]$ classloader -c 41e41a92 file:/root/.arthas/lib/3.5.3/arthas/arthas-core.jar Affect(row-cnt:2) cost in 0 ms.[arthas@8]$ classloader -c 16b4a017 not a URLClassLoader. Affect(row-cnt:0) cost in 0 ms.[arthas@8]$ classloader -c 18b4aac2 -r java/lang/String.classjar:file:/usr/lib/jvm/java-1.8-openjdk/jre/lib/rt.jar!/java/lang/String.class Affect(row-cnt:1) cost in 1 ms.monitor/watch/trace相關(guān)
請注意,這些命令,都通過字節(jié)碼增強技術(shù)來實現(xiàn)的,會在指定類的方法中插入一些切面來實現(xiàn)數(shù)據(jù)統(tǒng)計和觀測,因此在線上、預(yù)發(fā)使用時,請盡量明確需要觀測的類、方法以及條件,診斷結(jié)束要執(zhí)行 stop 或?qū)⒃鰪娺^的類執(zhí)行 reset 命令。
不匹配子類
默認情況下 watch/trace/monitor/stack/tt 命令都會匹配子類。如果想不匹配,可以通過全局參數(shù)關(guān)掉。
options disable-sub-class true使用 -v 參數(shù)打印更多信息
watch/trace/monitor/stack/tt 命令都支持 -v 參數(shù)
當(dāng)命令執(zhí)行之后,沒有輸出結(jié)果。有兩種可能:
但用戶區(qū)分不出是哪種情況。
使用 -v選項,則會打印Condition express的具體值和執(zhí)行結(jié)果,方便確認。
消耗時間過濾
watch/stack/trace 都支持通過 #cost 來過濾消耗時間。單位:ms
monitor
方法執(zhí)行監(jiān)控。對匹配 class-pattern/method-pattern/condition-express的類、方法的調(diào)用進行監(jiān)控。
監(jiān)控一段時間類的方法調(diào)用情況。
USAGE: monitor [-b] [-c <value>] [--exclude-class-pattern <value>] [-h] [-n <value> ] [--listenerId <value>] [-E <value>] [-v] class-pattern method-pattern [condition-express]monitor 命令是一個非實時返回命令。實時返回命令是輸入之后立即返回,而非實時返回的命令,則是不斷的等待目標(biāo) Java 進程返回信息,直到用戶輸入 Ctrl+C 為止。
服務(wù)端是以任務(wù)的形式在后臺跑任務(wù),植入的代碼隨著任務(wù)的中止而不會被執(zhí)行,所以任務(wù)關(guān)閉后,不會對原有性能產(chǎn)生太大影響,而且原則上,任何Arthas命令不會引起原有業(yè)務(wù)邏輯的改變。
監(jiān)控的維度說明
| timestamp | 時間戳 |
| class | Java類 |
| method | 方法(構(gòu)造方法、普通方法) |
| total | 調(diào)用次數(shù) |
| success | 成功次數(shù) |
| fail | 失敗次數(shù) |
| rt | 平均RT |
| fail-rate | 失敗率 |
參數(shù)說明
方法擁有一個命名參數(shù) [c:],意思是統(tǒng)計周期(cycle of output),擁有一個整型的參數(shù)值
| class-pattern | 類名表達式匹配 |
| method-pattern | 方法名表達式匹配 |
| condition-express | 條件表達式,ognl表達式 |
| E | 開啟正則表達式匹配,默認為通配符匹配 |
| c | 統(tǒng)計周期,默認值為120秒 |
| [b] | 在方法調(diào)用之前計算condition-express |
| exclude-class-pattern | 排除某些類 |
| -n, --limits | 執(zhí)行次數(shù)限制。 |
示例:
Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 719 ms, listenerId: 1timestamp class method total success fail avg-rt(ms) fail-rate --------------------------------------------------------------------------------2021-07-28 com.X.clou get 1 0 1 13.4 100. 19:15:23 d.assets.service. 7 00% impl.DataFileServ iceImpl timestamp class method total success fail avg-rt(ms) fail-rate --------------------------------------------------------------------------------2021-07-28 com.X.clou get 0 0 0 0.00 0.00 19:15:28 d.assets.service. % impl.DataFileServ iceImpl timestamp class method total success fail avg-rt(ms) fail-ratewatch
方法執(zhí)行數(shù)據(jù)觀測。能方便的觀察到指定方法的調(diào)用情況。能觀察到的范圍為:返回值、拋出異常、入?yún)?#xff0c;通過編寫 OGNL 表達式進行對應(yīng)變量的查看。
USAGE: watch [-b] [-e] [--exclude-class-pattern <value>] [-x <value>] [-f] [-h] [-n <value>] [--listenerId <value>] [-E] [-M <value>] [-s] [-v] class-pattern method-pattern [express] [condition-express]參數(shù)說明
watch 的參數(shù)比較多,主要是因為它能在 4 個不同的場景觀察對象
| class-pattern | 類名表達式匹配 |
| method-pattern | 方法名表達式匹配 |
| express | 觀察表達式,ognl |
| condition-express | 條件表達式,ognl |
| [b],–before | 在方法調(diào)用之前觀察 |
| [e],–exception | 在方法異常之后觀察 |
| [s],–succes | 在方法返回之后觀察 |
| [f],–finish | 在方法結(jié)束之后(正常返回和異常返回)觀察 |
| [E] | 開啟正則表達式匹配,默認為通配符匹配 |
| [x:] | 指定輸出結(jié)果的屬性遍歷深度,默認為 1 |
| exclude-class-pattern | 排除某些類 |
| -n, --limits | 執(zhí)行次數(shù)限制 |
| M | 返回結(jié)果size限制,默認:10M |
特別說明:
- watch 命令定義了4個觀察事件點,即 -b 方法調(diào)用前,-e 方法異常后,-s 方法返回后,-f 方法結(jié)束后
- 4個觀察事件點 -b、-e、-s 默認關(guān)閉,-f 默認打開,當(dāng)指定觀察點被打開后,在相應(yīng)事件點會對觀察表達式進行求值并輸出
- 這里要注意方法入?yún)⒑头椒ǔ鰠⒌膮^(qū)別,有可能在中間被修改導(dǎo)致前后不一致,除了 -b 事件點 params 代表方法入?yún)⑼?#xff0c;其余事件都代表方法出參
- 當(dāng)使用 -b 時,由于觀察事件點是在方法調(diào)用前,此時返回值或異常均不存在
表達式
這里重點要說明的是觀察表達式,觀察表達式的構(gòu)成主要由 ognl 表達式組成,所以你可以這樣寫"{params,returnObj}",只要是一個合法的 ognl 表達式,都能被正常支持。
觀察的維度也比較多,主要體現(xiàn)在參數(shù) advice 的數(shù)據(jù)結(jié)構(gòu)上。Advice 參數(shù)最主要是封裝了通知節(jié)點的所有信息。
表達式核心變量
無論是匹配表達式也好、觀察表達式也罷,他們核心判斷變量都是圍繞著一個 Arthas 中的通用通知對象 Advice 進行。
public class Advice {private final ClassLoader loader;private final Class<?> clazz;private final ArthasMethod method;private final Object target;private final Object[] params;private final Object returnObj;private final Throwable throwExp;private final boolean isBefore;private final boolean isThrow;private final boolean isReturn;// getter/setter }不同變量的含義
| loader | 本次調(diào)用類所在的 ClassLoader |
| clazz | 本次調(diào)用類的 Class 引用 |
| method | 本次調(diào)用方法反射引用 |
| target | 本次調(diào)用類的實例 |
| params | 本次調(diào)用參數(shù)列表,這是一個數(shù)組,如果方法是無參方法則為空數(shù)組 |
| returnObj | 本次調(diào)用返回的對象。當(dāng)且僅當(dāng) isReturn==true 成立時候有效,表明方法調(diào)用是以正常返回的方式結(jié)束。如果當(dāng)前方法無返回值 void,則值為 null |
| throwExp | 本次調(diào)用拋出的異常。當(dāng)且僅當(dāng) isThrow==true 成立時有效,表明方法調(diào)用是以拋出異常的方式結(jié)束。 |
| isBefore | 輔助判斷標(biāo)記,當(dāng)前的通知節(jié)點有可能是在方法一開始就通知,此時 isBefore==true 成立,同時 isThrow==false 和 isReturn==false,因為在方法剛開始時,還無法確定方法調(diào)用將會如何結(jié)束。 |
| isThrow | 輔助判斷標(biāo)記,當(dāng)前的方法調(diào)用以拋異常的形式結(jié)束。 |
| isReturn | 輔助判斷標(biāo)記,當(dāng)前的方法調(diào)用以正常返回的形式結(jié)束。 |
示例
watch com.x.cloud.assets.service.impl.DataFileServiceImpl hitByMd5 '{params,returnObj}' Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 549 ms, listenerId: 5 #調(diào)用的方法 method=com.x.cloud.assets.service.impl.DataFileServiceImpl.hitByMd5 location=AtExit #result 代表 ognl的結(jié)果, #cost :消耗時間 #ts :時間戳 ts=2021-07-28 19:37:14; [cost=3.741657ms] result=@ArrayList[@Object[][isEmpty=false;size=1], #第一個表達式的值,params@Boolean[false], #第一個表達式的值,returnObj ] method=com.x.cloud.assets.service.impl.DataFileServiceImpl$$EnhancerBySpringCGLIB$$22ae6297.hitByMd5 location=AtExit ts=2021-07-28 19:37:14; [cost=5.53776ms] result=@ArrayList[@Object[][isEmpty=false;size=1],@Boolean[false], ]trace
方法內(nèi)部調(diào)用路徑,并輸出方法路徑上的每個節(jié)點上耗時。
trace 命令能主動搜索 class-pattern/method-pattern 對應(yīng)的方法調(diào)用路徑,渲染和統(tǒng)計整個調(diào)用鏈路上的所有性能開銷和追蹤調(diào)用鏈路。
USAGE: trace [--exclude-class-pattern <value>] [-h] [-n <value>] [--listenerId <value>] [-p <value>] [-E] [--skipJDKMethod <value>] [-v] class-pattern method-pattern [condition-express]參數(shù)說明
| class-pattern | 類名表達式匹配 |
| method-pattern | 方法名表達式匹配 |
| condition-express | 條件表達式 |
| [E] | 開啟正則表達式匹配,默認為通配符匹配 |
| [n:] | 命令執(zhí)行次數(shù) |
| #cost | 方法執(zhí)行耗時 |
| exclude-class-pattern | 排除某些類 |
| -n, --limits | 執(zhí)行次數(shù)限制 |
| -p, --path |
這里重點要說明的是觀察表達式,觀察表達式的構(gòu)成主要由 ognl 表達式組成,所以你可以這樣寫"{params,returnObj}",只要是一個合法的 ognl 表達式,都能被正常支持。
觀察的維度也比較多,主要體現(xiàn)在參數(shù) advice 的數(shù)據(jù)結(jié)構(gòu)上。Advice 參數(shù)最主要是封裝了通知節(jié)點的所有信息。
trace原理:
每一個invokevirtual都對應(yīng)一個 trace結(jié)果里的entry。
所以,trace實際上是在每一個invokevirtual 前后插入代碼,然后統(tǒng)計調(diào)用的時間。
trace本身只能拿到當(dāng)前method的字節(jié)碼,所以它只能trace當(dāng)前method里的 invokevirtual,再深層的invokevirtual,它并不能知道。
包含jdk的函數(shù)
- --skipJDKMethod <value> skip jdk method trace, default value true.
默認情況下,trace不會包含jdk里的函數(shù)調(diào)用,如果希望trace jdk里的函數(shù),需要顯式設(shè)置--skipJDKMethod false。
trace多個類或者多個函數(shù)
trace命令只會trace匹配到的函數(shù)里的子調(diào)用,并不會向下trace多層。因為trace是代價比較貴的,多層trace可能會導(dǎo)致最終要trace的類和函數(shù)非常多。
可以用正則表匹配路徑上的多個類和函數(shù),一定程度上達到多層trace的效果。
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3示例
trace com.x.cloud.assets.service.impl.DataFileServiceImpl hi Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 544 ms, listenerId: 10 `---ts=2021-07-28 20:07:10;thread_name=XNIO-1 task-90;id=576;is_daemon=false;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@13cf7d52`---[12.192686ms] com.x.cloud.assets.service.impl.DataFileServiceImpl$$EnhancerBySpringCGLIB$$22ae6297:hitByMd5()`---[12.01052ms] org.springframework.cglib.proxy.MethodInterceptor:intercept()`---[11.760014ms] com.x.cloud.assets.service.impl.DataFileServiceImpl:hitByMd5()+---[0.074797ms] cn.hutool.core.text.CharSequenceUtil:isBlank() #111#可以看到這個調(diào)用時間最長`---[11.478036ms] com.x.cloud.assets.service.impl.DataFileServiceImpl:getByMd5() #115stack
輸出當(dāng)前方法被調(diào)用的調(diào)用路徑
USAGE: stack [--exclude-class-pattern <value>] [-h] [-n <value>] [--listenerId <value>] [-E] [-v] class-pattern [method-pattern] [condition-express]參數(shù)與trace相同。
輸出結(jié)果類似 Java拋出異常的stack。
tt (Time Tunnel)
方法執(zhí)行數(shù)據(jù)的時空隧道,記錄下指定方法每次調(diào)用的入?yún)⒑头祷匦畔?#xff0c;并能對這些不同的時間下調(diào)用進行觀測。
watch 雖然很方便和靈活,但需要提前想清楚觀察表達式的拼寫,這對排查問題而言要求太高,因為很多時候我們并不清楚問題出自于何方,只能靠蛛絲馬跡進行猜測。這個時候如果能記錄下當(dāng)時方法調(diào)用的所有入?yún)⒑头祷刂怠伋龅漠惓φ麄€問題的思考與判斷非常有幫助。于是乎,TimeTunnel 命令就誕生了。
USAGE: tt [-d] [--delete-all] [--exclude-class-pattern <value>] [-x <value>] [-h] [ -i <value>] [-n <value>] [-l] [--listenerId <value>] [-p] [-E] [--replay-interval <value>] [--replay-times <value>] [-s <value>] [-M <value>] [-t] [-v] [-w <value>] [class-pattern] [method-pattern] [condition-express]參數(shù)說明
| -d, --delete | Delete time fragment specified by index |
| –delete-all | Delete all the time fragments |
| –exclude-class-pattern | exclude class name pattern, use either ‘.’ or ‘/’ as separator |
| -x, --expand | Expand level of object (1 by default) |
| -h, --help | this help |
| -i, --index | Display the detailed information from specified time fragment |
| -n, --limits | 執(zhí)行次數(shù)限制 |
| -l, --list | List all the time fragments |
| –listenerId | The special listenerId |
| -p, --play | Replay the time fragment specified by index |
| -E, --regex | Enable regular expression to match (wildcard matching by default) |
| –replay-interval | replay interval for play tt with option r greater than 1 |
| –replay-times | execution times when play tt |
| -s, --search-express | 通過ognl 表達式篩選記錄 |
| -M, --sizeLimit | Upper size limit in bytes for the result (10 * 1024 * 1024 by default) |
| -t, --time-tunnel | 記錄下方法的每次執(zhí)行情況 |
| -v, --verbose | Enables print verbose information, default value false. |
| -w, --watch-express <value> | 觀察某個ognl表達式 |
| Path and classname of Pattern Matching | |
| Method of Pattern Matching | |
| Conditional expression in ognl style |
表格字段說明
| INDEX | 時間片段記錄編號,每一個編號代表著一次調(diào)用,后續(xù)tt還有很多命令都是基于此編號指定記錄操作,非常重要。 |
| TIMESTAMP | 方法執(zhí)行的本機時間,記錄了這個時間片段所發(fā)生的本機時間 |
| COST(ms) | 方法執(zhí)行的耗時 |
| IS-RET | 方法是否以正常返回的形式結(jié)束 |
| IS-EXP | 方法是否以拋異常的形式結(jié)束 |
| OBJECT | 執(zhí)行對象的hashCode(),注意,曾經(jīng)有人誤認為是對象在JVM中的內(nèi)存地址,但很遺憾他不是。但他能幫助你簡單的標(biāo)記當(dāng)前執(zhí)行方法的類實體 |
| CLASS | 執(zhí)行的類名 |
| METHOD | 執(zhí)行的方法名 |
條件表達式
不知道大家是否有在使用過程中遇到以下困惑
- Arthas 似乎很難區(qū)分出重載的方法
- 我只需要觀察特定參數(shù),但是 tt 卻全部都給我記錄了下來
條件表達式也是用 OGNL 來編寫,核心的判斷對象依然是 Advice 對象。除了 tt 命令之外,watch、trace、stack 命令也都支持條件表達式。
解決方法重載
tt -t *Test print params.length==1
通過制定參數(shù)個數(shù)的形式解決不同的方法簽名,如果參數(shù)個數(shù)一樣,你還可以這樣寫
tt -t *Test print 'params[1] instanceof Integer'
解決指定參數(shù)
tt -t *Test print params[0].mobile=="13989838402"
檢索調(diào)用記錄
當(dāng)用 tt 記錄了一大片的時間片段之后,希望能從中篩選出自己需要的時間片段,這個時候就需要對現(xiàn)有記錄進行檢索。
tt -s 'method.name=="primeFactors"'replay
tt 命令由于保存了當(dāng)時調(diào)用的所有現(xiàn)場信息,所以我們可以自己主動對一個 INDEX 編號的時間片自主發(fā)起一次調(diào)用,從而解放你的溝通成本。此時你需要 -p 參數(shù)。通過 --replay-times 指定 調(diào)用次數(shù),通過 --replay-interval 指定多次調(diào)用間隔(單位ms, 默認1000ms)
tt -i 1004 -p調(diào)用方法
#獲取類的靜態(tài)字段、調(diào)用類的靜態(tài)方法 tt -w '@demo.MathGame@random.nextInt(100)' -x 1 -i 1000需要強調(diào)的點
ThreadLocal 信息丟失
很多框架偷偷的將一些環(huán)境變量信息塞到了發(fā)起調(diào)用線程的 ThreadLocal 中,由于調(diào)用線程發(fā)生了變化,這些 ThreadLocal 線程信息無法通過 Arthas 保存,所以這些信息將會丟失。
一些常見的 CASE 比如:鷹眼的 TraceId 等。
引用的對象
需要強調(diào)的是,tt 命令是將當(dāng)前環(huán)境的對象引用保存起來,但僅僅也只能保存一個引用而已。如果方法內(nèi)部對入?yún)⑦M行了變更,或者返回的對象經(jīng)過了后續(xù)的處理,那么在 tt 查看的時候?qū)o法看到當(dāng)時最準(zhǔn)確的值。這也是為什么 watch 命令存在的意義。
示例
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD ------------------------------------------------------------------------------------------------------------------------------------------------------------1000 2021-07-29 08:27:34 10.704542 true false 0x43051a8d DataFileServiceImpl hitByMd5 1001 2021-07-29 08:27:34 17.006056 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297 1002 2021-07-29 08:27:35 3.067571 true false 0x43051a8d DataFileServiceImpl hitByMd5 1003 2021-07-29 08:27:35 3.586726 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297 1004 2021-07-29 08:27:35 3.380568 true false 0x43051a8d DataFileServiceImpl hitByMd5 1005 2021-07-29 08:27:35 3.772195 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297 1006 2021-07-29 08:27:36 3.040024 true false 0x43051a8d DataFileServiceImpl hitByMd5 1007 2021-07-29 08:27:36 3.440104 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297 1008 2021-07-29 08:27:36 3.19423 true false 0x43051a8d DataFileServiceImpl hitByMd5 1009 2021-07-29 08:27:36 3.543442 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297 1010 2021-07-29 08:27:36 3.331589 true false 0x43051a8d DataFileServiceImpl hitByMd5 1011 2021-07-29 08:27:36 3.706372 true false 0xbffac3e5 DataFileServiceImpl$$EnhancerBySpri hitByMd5 ngCGLIB$$22ae6297profiler/火焰圖
profiler
使用async-profiler對應(yīng)用采樣,生成火焰圖
profiler 命令支持生成應(yīng)用熱點的火焰圖。本質(zhì)上是通過不斷的采樣,然后把收集到的采樣結(jié)果生成火焰圖。
profiler action [actionArg] USAGE: profiler [--allkernel] [--alluser] [-d <value>] [-e <value>] [--exclude <value>] [-f <value>] [--format <value>] [-b <value>] [-h] [--include <value>] [ -i <value>] [--threads] action [actionArg]參數(shù)說明
| action | 要執(zhí)行的操作 |
| actionArg | 屬性名模式 |
| [i:],–interval | 采樣間隔(單位:ns)(默認值:10’000’000,即10 ms) |
| [f:],–file | 將輸出轉(zhuǎn)儲到指定路徑。file參數(shù)支持一些變量:時間戳:%t;進程ID:%p |
| [d:],–duration | 運行評測指定秒 |
| [e:],–event | 要跟蹤哪個事件(cpu, alloc, lock, cache-misses等),默認是cpu |
| -b, --framebuf | size of the buffer for stack frames |
| –exclude | 排除包含 指定模式的跟蹤,for example: ‘Unsafe.park’。include/exclude 都支持設(shè)置多個值 ,但是需要配置在命令行的最后 |
| –format | dump文件的格式:svg, html, jfr,默認:svg。 |
| –threads | 指定線程id。 |
| –include | 包含 指定模式的跟蹤,for example: ‘Unsafe.park’ |
| –allkernel | include only kernel-mode events |
| –alluser | include only user-mode events |
action 示例
profiler start #啟動profilerprofiler stop #停止profilerprofiler list # list all supported events profiler actions # list all supported actions profiler start --event alloc profiler stop --format svg # output file format, support svg,html,jfr profiler stop --file /tmp/result.html profiler stop --threads profiler start --include 'java/*' --include 'demo/*' --exclude '*Unsafe.park*' profiler status profiler resume # Start or resume profiling without resetting collected data. profiler getSamples # Get the number of samples collected during the profiling session profiler dumpFlat # Dump flat profile, i.e. the histogram of the hottest methods profiler dumpCollapsed # Dump profile in 'collapsed stacktraces' format profiler dumpTraces # Dump collected stack traces profiler execute 'start,framebuf=5000000' # Execute an agent-compatible profiling command profiler execute 'stop,file=/tmp/result.svg' # Execute an agent-compatible profiling commandaction list
Supported Actions: [ resume #恢復(fù)采樣 , dumpCollapsed , getSamples #獲取已采集的sample的數(shù)量 , start #啟動profiler , list #列出所有event , execute #使用execute來執(zhí)行復(fù)雜的命令 , version #查看版本 , stop #停止profiler , load , dumpFlat , actions #列出所有action , dumpTraces , status #查看profiler狀態(tài) ]event list
$ profiler list Basic events:cpu # failedalloc # failedlock # ok wall # okitimer # ok Java method calls:ClassName.methodName # ok Perf events:page-faultscontext-switchescyclesinstructionscache-referencescache-missesbranchesbranch-missesbus-cyclesL1-dcache-load-missesLLC-load-missesdTLB-load-missesmem:breakpoint #Unsupported event typetrace:tracepoint #Unsupported event typeexecute命令格式
?
火焰圖的理解
火焰圖坐標(biāo):
- X:表示資源使用情況,X軸越長,代表使用的越多。沒有方向。比如cpu 那么x軸長度越大,占用的cpu資源就越多。
- Y:y 軸表示調(diào)用棧,每一層都是一個函數(shù)。調(diào)用棧越深,火焰就越高,頂部就是正在執(zhí)行的函數(shù),下方都是它的父函數(shù)。
火焰圖就是看頂層的哪個函數(shù)占據(jù)的寬度最大。只要有"平頂"(plateaus),就表示該函數(shù)可能存在性能問題。
顏色沒有特殊含義,因為火焰圖表示的是 CPU 的繁忙程度,所以一般選擇暖色調(diào)。
通過瀏覽器查看arthas-output下面的profiler結(jié)果
默認情況下,arthas使用3658端口,則可以打開: http://localhost:3658/arthas-output/ 查看到arthas-output目錄下面的profiler結(jié)果。
默認根目錄是:~/.arthas/,或者是 arthas-boot.jar所在目錄
鑒權(quán)
auth
鑒權(quán)
options
options
查看或設(shè)置Arthas全局開關(guān)。
USAGE: options [-h] [options-name] [options-value]| unsafe | false | 是否支持對系統(tǒng)級別的類進行增強,打開該開關(guān)可能導(dǎo)致把JVM搞掛,請慎重選擇! |
| dump | false | 是否支持被增強了的類dump到外部文件中,如果打開開關(guān),class文件會被dump到/${application working dir}/arthas-class-dump/目錄下,具體位置詳見控制臺輸出 |
| batch-re-transform | true | 是否支持批量對匹配到的類執(zhí)行retransform操作 |
| json-format | false | 是否支持json化的輸出 |
| disable-sub- class | false | 是否禁用子類匹配,默認在匹配目標(biāo)類的時候會默認匹配到其子類,如果想精確匹配,可以關(guān)閉此開關(guān) |
| support-default-method | true | 是否支持匹配到default method,默認會查找interface,匹配里面的default method。參考 #1105 |
| save-result | false | 是否打開執(zhí)行結(jié)果存日志功能,打開之后所有命令的運行結(jié)果都將保存到~/logs/arthas-cache/result.log中 |
| job-timeout | 1d | 異步后臺任務(wù)的默認超時時間,超過這個時間,任務(wù)自動停止;比如設(shè)置 1d, 2h, 3m, 25s,分別代表天、小時、分、秒 |
| print-parent-fields | true | 是否打印在parent class里的filed |
后臺異步任務(wù)
當(dāng)線上出現(xiàn)偶發(fā)的問題,比如需要watch某個條件,而這個條件一天可能才會出現(xiàn)一次時,異步后臺任務(wù)就派上用場了。
- 使用 > 將結(jié)果重寫向到日志文件,使用 & 指定命令是后臺運行,session斷開不影響任務(wù)執(zhí)行(生命周期默認為1天)
- jobs——列出所有job
- kill——強制終止任務(wù)
- fg——將暫停的任務(wù)拉到前臺執(zhí)行
- bg——將暫停的任務(wù)放到后臺執(zhí)行
其他
logger
查看logger信息,更新logger level
USAGE: logger [-c <value>] [--classLoaderClass <value>] [-h] [--include-no-appender] [-l <value>] [-n <value>]-c, --classloader <value> --classLoaderClass <value> The class name of the special class's classLoader. -h, --help this help --include-no-appender include the loggers which don't have appenders, default value false -l, --level <value> set logger level -n, --name <value> logger name # logger name ROOT class ch.qos.logback.classic.Logger classLoader org.springframework.boot.loader.LaunchedURLClassLoader@3e10dc6 classLoaderHash 3e10dc6 level INFO effectiveLevel INFO additivity true codeSource jar:file:/cloud/app.jar!/BOOT-INF/lib/logback-classic-1.2.3.jar!/ appenders name console class ch.qos.logback.core.ConsoleAppender classLoader org.springframework.boot.loader.LaunchedURLClassLoader@3e10dc6 classLoaderHash 3e10dc6 target System.out name file class ch.qos.logback.core.rolling.RollingFileAppender classLoader org.springframework.boot.loader.LaunchedURLClassLoader@3e10dc6 classLoaderHash 3e10dc6 file logs/2021-07/2021-07-29.logmbean
查看 Mbean 的信息。
USAGE: mbean [-h] [-i <value>] [-m] [-n <value>] [-E] [name-pattern] [attribute-pattern] -h, --help this help -i, --interval <value> The interval (in ms) between two executions. -m, --metadata Show metadata of mbean. -n, --number-of-execution <value> The number of times this command will be executed. -E, --regex Enable regular expression to match attribute name (wildcard matching by default). <name-pattern> ObjectName pattern, see javax.management.ObjectName for more detail. It looks like this: domain: key-property-list For example: java.lang:name=G1 Old Gen,type=MemoryPool java.lang:name=*,type=MemoryPool <attribute-pattern> Attribute name pattern.注意:ObjectName 的匹配規(guī)則與正常的通配符存在差異,詳細參見:javax.management.ObjectName
實戰(zhàn)
參考
視頻教程:https://start.aliyun.com/handson-lab?category=arthas
活用ognl:https://github.com/alibaba/arthas/issues/11
profiler問題
1、No AllocTracer symbols found. Are JDK debug symbols installed?
? 可能需要安裝帶有OpenJDK調(diào)試符號的包,有關(guān)詳細信息,請參閱分配分析。
? 注意,除了HotSpot(例如Zing)JVM支持之外,其它的JVM都不支持分配分析。
2、Perf events unavailable. See stderr of the target process
? perf_event_open()系統(tǒng)調(diào)用失敗,錯誤消息被打印到目標(biāo)JVM的錯誤流中。典型原因包括:
-
/proc/sys/kernel/perf_event_paranoid設(shè)置為受限模式(>=2);
-
seccomp禁用容器中的perf_event_open API;
-
操作系統(tǒng)在不虛擬化性能計數(shù)器的管理程序下運行;
-
當(dāng)前系統(tǒng)不支持perf_event_open API,例如WSL。
如果無法更改配置,則可以返回到使用-e itimer分析模式。它類似于cpu模式,但不需要性能事件支持,但是其存在一個不足,不能夠收集內(nèi)核堆棧跟蹤的信息;
參考:https://my.oschina.net/u/1760791/blog/4773494
https://tkstorm.com/posts-list/computer-applications/docker/docker-tips/
在容器中很難解決
3、frame_buffer_overflow
輸出中的此消息表示沒有足夠的空間存儲所有調(diào)用跟蹤,考慮使用-b選項增加幀緩沖區(qū)大小。
javax.management.ObjectName
總結(jié)
- 上一篇: Redis与Lua详解
- 下一篇: Minio进阶