tag: java 診斷 堆疊 線上除錯 耗時 死鎖 arthas 阿里巴巴
Arthas (阿爾薩斯)
Arthas
是 Alibaba 開源的Java診斷工具,深受開發者喜愛。
官網文件:https://arthas.aliyun.com/doc/
當你遇到以下類似問題而束手無策時,Arthas
可以幫助你解決:
- 這個類從哪個 jar 包載入的?為什麼會報各種類相關的 Exception?
- 我改的程式碼為什麼沒有執行到?難道是我沒 commit?分支搞錯了?
- 遇到問題無法線上上 debug,難道只能通過加日誌再重新發布嗎?
- 線上遇到某個使用者的資料處理有問題,但線上同樣無法 debug,線下無法重現!
- 是否有一個全域性視角來檢視系統的執行狀況?
- 有什麼辦法可以監控到JVM的實時執行狀態?
- 怎麼快速定位應用的熱點,生成火焰圖?
- 怎樣直接從JVM內查詢某個類的例項?
Arthas
支援JDK 6+,支援Linux/Mac/Windows,採用命令列互動模式,同時提供豐富的 Tab
自動補全功能,進一步方便進行問題的定位和診斷。
安裝
快速安裝
1.1.1 使用arthas-boot(推薦)
下載arthas-boot.jar
,然後用java -jar
的方式啟動:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
列印幫助資訊:
java -jar arthas-boot.jar -h
如果下載速度比較慢,可以使用aliyun的映象:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
使用as.sh
方式安裝
Arthas 支援在 Linux/Unix/Mac 等平臺上一鍵安裝,請複製以下內容,並貼上到命令列中,敲 回車
執行即可:
curl -L https://arthas.aliyun.com/install.sh | sh
上述命令會下載啟動指令碼檔案 as.sh
到當前目錄,你可以放在任何地方或將其加入到 $PATH
中。
直接在shell下面執行./as.sh
,就會進入互動介面。
也可以執行./as.sh -h
來獲取更多引數資訊。
全量安裝 (線上環境無外網訪問許可權)
# java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 24438 org.elasticsearch.bootstrap.Elasticsearch
1
[ERROR] Can not read arthas version from: https://arthas.aliyun.com/api/latest_version
[ERROR] Can not find Arthas under local: /root/.arthas/lib and remote repo mirror: aliyun
[ERROR] Unable to download arthas from remote server, please download the full package according to wiki: https://github.com/alibaba/arthas
當使用快速安裝方式線上上環境進行連線Java服務的時候,很有可能因為線上環境無外部網路訪問許可權,導致Arthas無法獲取 arthas-core 等jar包,無法執行。
這時候就需要全量安裝Arthas包。
安裝方法 : ( 包大小13MB )
#### 獲取 arthas 全量包
curl -Lo arthas-packaging-latest-bin.zip 'https://arthas.aliyun.com/download/latest_version?mirror=aliyun'
unzip -d arthas-latest-bin arthas-packaging-latest-bin.zip
#### 開始執行
java -jar ahthas-boot.jar
[INFO] arthas-boot version: 3.5.4
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 27878 /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib/tsf-ratelimit-1.29.1.jar
1
[INFO] arthas home: /root
[INFO] Try to attach process 27878
[INFO] Attach process 27878 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.4
main_class
pid 27878
time 2021-09-07 19:31:47
通過 rpm/deb 來安裝
這部分見官方文件.
快速入門
arthas
需要使用到 jps 命令,所以要保證 openjdk-devel
包已經安裝。
jps || yum -y install java-1.8.0-openjdk-devel
執行 arthas:
# java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Process 5201 already using port 3658
[INFO] Process 5201 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 5201 cloud-access-auth-1.18.1.jar
[2]: 14419 tsf-stack-base-1.0.0.jar
[3]: 27862 cloud-access-gateway-1.18.1.jar
[4]: 6550 tsfmanager-operation-1.29.1.jar
提示1:當 arthas 給出的程式列表不能確定程式資訊的時候,我們可以通過在命令列輸入
jps -lmv
檢視詳細的 java 程式資訊,來確定我們要檢視的 java 程式號。提示2:當提示如下資訊時:
Arthas script version: 3.0.4 Calculating attach execution time... Attaching to 24110 using version 3.0.4... Start arthas failed, exception stack trace: java.lang.InternalError: instrument library is missing in target VM at sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:105) at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:84) at com.taobao.arthas.core.Arthas.<init>(Arthas.java:25) at com.taobao.arthas.core.Arthas.main(Arthas.java:96) Caused by: com.sun.tools.attach.AgentLoadException: Failed to load agent library at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:224) at sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:58) at sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:79) at sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:103) ... 3 more attach to target jvm (24110) failed, check /root/logs/arthas/arthas.log or stderr of target jvm for any exceptions.
我們需要重新啟動一下該程式,然後再執行 arthas ,連線到後臺 java 程式即可。
下面的 java 程式編號即當前主機已經執行的 java 服務,輸入編號即可進入 arthas 的互動式介面。
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 5201 cloud-access-auth-1.18.1.jar
[2]: 14419 tsf-stack-base-1.0.0.jar
[3]: 27862 cloud-access-gateway-1.18.1.jar
[4]: 6550 tsfmanager-operation-1.29.1.jar
1
[INFO] local lastest version: 3.5.3, remote lastest version: 3.5.4, try to download from remote.
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.5.4?mirror=aliyun
[INFO] Download arthas success.
[INFO] arthas home: /root/.arthas/lib/3.5.4/arthas
[INFO] The target process already listen port 3658, skip attach.
[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 5201
time 2021-09-03 09:55:42
[arthas@5201]$
當出現上述彩條 ARTHAS 字元提示的時候,就表示已經正常連線到指定的 Java 程式,隨即進入到下面的 arthas@PID
命令提示符。
功能使用
dashboard 指令 -- 總覽JVM資訊
在 arthas 命令提示符下鍵入dashboard
回車,會展示當前程式的資訊,按q
退出。
dashboard 會實時輸出該java程式的JVM資訊,包括執行緒、程式、記憶體、堆疊、以及當前系統執行時資訊。
[arthas@5201]$ dashboard -h
USAGE:
dashboard [-h] [-i <value>] [-n <value>]
SUMMARY:
Overview of target jvm's thread, memory, gc, vm, tomcat info.
EXAMPLES:
dashboard
dashboard -n 10
dashboard -i 2000
WIKI:
https://arthas.aliyun.com/doc/dashboard
OPTIONS:
-h, --help this help
-i, --interval <value> The interval (in ms) between two executions, default is 5000 ms.
-n, --number-of-execution <value> The number of times this command will be executed.
help 指令
該指令用以列出所有 arthas 互動式介面支援的 子命令 列表。
[arthas@5201]$ help
NAME DESCRIPTION
help Display Arthas Help
auth Authenticates the current session
keymap Display all the available keymap for the specified connection.
sc Search all the classes loaded by JVM
sm Search the method of classes loaded by JVM
classloader Show classloader info
jad Decompile class
getstatic Show the static field of a class
monitor Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
stack Display the stack trace for the specified class and method
thread Display thread info, thread stack
trace Trace the execution time of specified method invocation.
watch Display the input/output parameter, return object, and thrown exception of specified method invocation
tt Time Tunnel
jvm Display the target JVM information
perfcounter Display the perf counter information.
ognl Execute ognl expression.
mc Memory compiler, compiles java files into bytecode and class files in memory.
redefine Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)
retransform Retransform classes. @see Instrumentation#retransformClasses(Class...)
dashboard Overview of target jvm's thread, memory, gc, vm, tomcat info.
dump Dump class byte array from JVM
heapdump Heap dump
options View and change various Arthas options
cls Clear the screen
reset Reset all the enhanced classes
version Display Arthas version
session Display current session information
sysprop Display, and change the system properties.
sysenv Display the system env.
vmoption Display, and update the vm diagnostic options.
logger Print logger info, and update the logger level
history Display command history
cat Concatenate and print files
base64 Encode and decode using Base64 representation
echo write arguments to the standard output
pwd Return working directory name
mbean Display the mbean information
grep grep command for pipes.
tee tee command for pipes.
profiler Async Profiler. https://github.com/jvm-profiling-tools/async-profiler
vmtool jvm tool
stop Stop/Shutdown Arthas server and exit the console.
每個子命令,都可以跟上 -h
來進一步獲取幫助用法資訊。
thread 指令
[arthas@5201]$ thread -h
USAGE:
thread [--all] [-h] [-b] [--lockedMonitors] [--lockedSynchronizers] [-i <value>] [--state <value>] [-n <value>] [id]
SUMMARY:
Display thread info, thread stack
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 page
-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
$ thread -i 5000
## 獲取時間跨度為5s的計算彙總資料
$ thread -n 3
## 根據 CPU 使用率排序,獲取從高到低的 3 個執行緒堆疊資訊
$ thread -b
## 僅檢視死鎖執行緒的堆疊資訊
$ thread --lockedSynchronizers
## 僅檢視同步器死鎖的執行緒堆疊資訊
stop / exit 停止 和 離開
stop
: 停止和退出 Arthas consol ,正常退出步驟。
exit
: 僅離開 Arthas consol,但是繫結到 Java 程式的 arthas 任務不會退出。
[SHELL]# java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 5201 cloud-access-auth-1.18.1.jar
[2]: 14419 tsf-stack-base-1.0.0.jar
[3]: 27862 cloud-access-gateway-1.18.1.jar
[4]: 6550 tsfmanager-operation-1.29.1.jar
1
[INFO] arthas home: /root/.arthas/lib/3.5.4/arthas
[INFO] Try to attach process 5201
[INFO] Attach process 5201 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.4
main_class
pid 5201
time 2021-09-03 13:05:51
[arthas@5201]$ exit
[SHELL]# java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Process 5201 already using port 3658 ## 由於上次並沒有 shutdown 關閉arthas與java程式的繫結,所以Arthas重新啟動的時候,檢測到仍然繫結到 5201 程式上面的。
[INFO] Process 5201 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 5201 cloud-access-auth-1.18.1.jar
[2]: 14419 tsf-stack-base-1.0.0.jar
[3]: 27862 cloud-access-gateway-1.18.1.jar
[4]: 6550 tsfmanager-operation-1.29.1.jar
我們通過 jstack -l 5201 來證實這一點
[root@VM-0-4-centos ~]# jstack -l 5201 | more
2021-09-03 13:08:16
Full thread dump OpenJDK 64-Bit Server VM (25.302-b08 mixed mode):
"arthas-NettyHttpTelnetBootstrap-3-3" #169 daemon prio=5 os_prio=0 tid=0x00007f314000b800 nid=0x5632 runnable [0x00007f30cb51a000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000e8cafb00> (a com.alibaba.arthas.deps.io.netty.channel.nio.SelectedSelectionKeySet)
- locked <0x00000000e8caf8a8> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000e8caf790> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)
at com.alibaba.arthas.deps.io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:68)
at com.alibaba.arthas.deps.io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:810)
at com.alibaba.arthas.deps.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:457)
at com.alibaba.arthas.deps.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at com.alibaba.arthas.deps.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at com.alibaba.arthas.deps.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"arthas-NettyHttpTelnetBootstrap-3-2" #168 daemon prio=5 os_prio=0 tid=0x00007f314000a000 nid=0x51ce runnable [0x00007f30d09f9000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000e8cac058> (a com.alibaba.arthas.deps.io.netty.channel.nio.SelectedSelectionKeySet)
- locked <0x00000000e8cabe00> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000e8cabce8> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)
at com.alibaba.arthas.deps.io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:68)
我們可以看到 5201 程式的java堆疊資訊,有 arthas 的執行緒正在執行中。
正常退出步驟:
[arthas@5201]$ stop
Resetting all enhanced classes ...
Affect(class count: 0 , method count: 0) cost in 0 ms, listenerId: 0
Arthas Server is going to shutdown...
[arthas@5201]$ session (f0151617-7fd2-4b4b-b79f-31d366a72fc5) is closed because server is going to shutdown.
[SHELL]# jstack -l 5201 | more
2021-09-03 13:10:16
Full thread dump OpenJDK 64-Bit Server VM (25.302-b08 mixed mode):
"Abandoned connection cleanup thread" #51 daemon prio=5 os_prio=0 tid=0x00007f30e0246000 nid=0x1d86 in Object.wait() [0x00007f3120393000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000e3280300> (a java.lang.ref.ReferenceQueue$Lock)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- <0x00000000e3280390> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"Tomcat JDBC Pool Cleaner[1450495309:1630634377161]" #50 daemon prio=5 os_prio=0 tid=0x00007f30e01e4800 nid=0x1d85 in Object.wait() [0x00007f3120494000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x00000000e3280540> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
Locked ownable synchronizers:
- None
可以看到,使用 stop
指令關閉arthas診斷程式後,java 程式上面的arthas執行緒繫結也一併退出了。
watch 指令 ⭐ -- 方法執行資料觀測
watch
指令算是 Arthas 中最常用的指令之一了,它能夠獲取指定包.類.方法
的入參
、自身類方法體內部物件
以及返回物件值
。
[arthas@5201]$ watch -h
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]
SUMMARY:
Display the input/output parameter, return object, and thrown exception of specified method invocation
The express may be one of the following expression (evaluated dynamically):
target : the object
clazz : the object's class
method : the constructor or method
params : the parameters array of method
params[0..n] : the element of parameters array
returnObj : the returned object of method
throwExp : the throw exception of method
isReturn : the method ended by return
isThrow : the method ended by throwing exception
#cost : the execution time in ms of method invocation
Examples:
watch org.apache.commons.lang.StringUtils isBlank
watch org.apache.commons.lang.StringUtils isBlank '{params, target, returnObj, throwExp}' -x 2
watch *StringUtils isBlank params[0] params[0].length==1
watch *StringUtils isBlank params '#cost>100'
watch -f *StringUtils isBlank params
watch *StringUtils isBlank params[0]
watch -E -b org\.apache\.commons\.lang\.StringUtils isBlank params[0]
watch javax.servlet.Filter * --exclude-class-pattern com.demo.TestFilter
WIKI:
https://arthas.aliyun.com/doc/watch
OPTIONS:
-b, --before Watch before invocation
-e, --exception Watch after throw exception
--exclude-class-pattern <value> exclude class name pattern, use either '.' or '/' as separator
-x, --expand <value> Expand level of object (1 by default)
-f, --finish Watch after invocation, enable by default
-h, --help this help
-n, --limits <value> Threshold of execution times
--listenerId <value> The special listenerId
-E, --regex Enable regular expression to match (wildcard matching by default)
-M, --sizeLimit <value> Upper size limit in bytes for the result (10 * 1024 * 1024 by default)
-s, --success Watch after successful invocation
-v, --verbose Enables print verbose information, default value false.
<class-pattern> The full qualified class name you want to watch
<method-pattern> The method name you want to watch
<express> The content you want to watch, written by ognl. Default value is '{params, target, returnObj}'
Examples:
params
params[0]
'params[0]+params[1]'
'{params[0], target, returnObj}'
returnObj
throwExp
target
clazz
method
<condition-express> Conditional expression in ognl style, for example:
TRUE : 1==1
TRUE : true
FALSE : false
TRUE : 'params.length>=0'
FALSE : 1==2
'#cost>100'
引數說明
watch 的引數比較多,主要是因為它能在 4 個不同的場景觀察物件
引數名稱 | 引數說明 |
---|---|
class-pattern | 類名錶達式匹配 |
method-pattern | 方法名錶達式匹配 |
express | 觀察表示式,預設值:{params, target, returnObj} |
condition-express | 條件表示式 |
[b] | 在方法呼叫之前觀察 |
[e] | 在方法異常之後觀察 |
[s] | 在方法返回之後觀察 |
[f] | 在方法結束之後(正常返回和異常返回)觀察 |
[E] | 開啟正規表示式匹配,預設為萬用字元匹配 |
[x:] | 指定輸出結果的屬性遍歷深度,預設為 1 |
這裡重點要說明的是觀察表示式,觀察表示式的構成主要由 #OGNL
表示式組成,所以你可以這樣寫"{params,returnObj}"
,只要是一個合法的 ognl 表示式,都能被正常支援。
觀察的維度也比較多,主要體現在引數 advice
的資料結構上。Advice
引數最主要是封裝了通知節點的所有資訊。請參考表示式核心變數中關於該節點的描述。
使用舉例:
我需要觀察cloud-access-auth-1.18.1.jar
程式在處理登入資訊時的登入方法資訊,日誌如下:
13:42:54.205 INFO [http-nio-7001-exec-4] c.t.c.access.sso.service.impl.AuthenticateService - [Access Auth] account login parameter. accountName:qcloudAdmin ,password:******
得到指定類名為AuthenticateService
。
我們帶到 Arthas 中進行 watch:
### 報名在日誌檔案中是簡寫,所以我這裡使用萬用字元方式匹配類名,第二個引數方法名我也用*代替,全部匹配
[arthas@5201]$ watch *AuthenticateService *
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 6) cost in 130 ms, listenerId: 16
### 從輸出資訊得知,在這個 Java 程式所有程式碼中匹配到有兩個類,一共6個方法
我們來點選頁面登入按鈕,看看 watch 中能觀察到哪些動作:
[arthas@5201]$ watch *AuthenticateService *
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 6) cost in 130 ms, listenerId: 16
#### 第一個方法開始執行 Begin
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 13:51:25; [cost=2.217281ms] result=@ArrayList[
@Object[][isEmpty=false;size=3],
@AuthenticateService[com.tencent.cloud.access.sso.service.impl.AuthenticateService@f5cadbf],
@AccessAuthPrincipal[com.tencent.cloud.access.sso.model.AccessAuthPrincipal@72f71bf6],
]
#### 第一個方法執行結束 End
#### 第二個方法開始執行 Begin
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.updateSession location=AtExit
ts=2021-09-03 13:51:25; [cost=0.956478ms] result=@ArrayList[
@Object[][isEmpty=false;size=2],
@AuthenticateService[com.tencent.cloud.access.sso.service.impl.AuthenticateService@f5cadbf],
@AuthenticationResponse[com.tencent.cloud.access.sso.model.AuthenticationResponse@6b2bae10],
]
#### 第二個方法執行退出 End
..............
在輸出資訊中我們可以看到,第一行有完整的方法路徑
,以及獲取的退出狀態location
。
- AtExit:表示正常退出。
- AtExceptionExit:表示異常退出。
第二行有方法執行的開始時間戳
以及cost 開銷
,最後一個為watch的結果。
這裡result
的 ArrayList 陣列是 watch
指令的強大之處,它預設包含三個物件:
params
: 入參,通常為陣列,這裡為@Object
物件target
: 執行中當前 this 物件,也就是這個類物件本身,這裡為@AuthenticateService
實體類物件returnObj
: 返回物件值,這裡為返回的@AccessAuthPrincipal
物件
我們重新執行一次 watch 指令,這次我們們精確指定類名和方法名,以及加一個-x
解析深度引數:
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 74 ms, listenerId: 17
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 14:10:15; [cost=3.289679ms] result=@ArrayList[
@Object[][
@String[qcloudAdmin],
@String[Bgi8c0yC+IAvRLkuQRy6kLQ6T2J/9PNrL6G/+KX9ppE=],
@String[127.0.0.1],
],
@AuthenticateService[
log=@Logger[Logger[com.tencent.cloud.access.sso.service.impl.AuthenticateService]],
sessionDAO=@RedisSessionDAO[com.tencent.cloud.access.sso.shiro.RedisSessionDAO@61813e98],
accountSessionService=@AccountSessionService[com.tencent.cloud.access.account.service.impl.AccountSessionService@30e815ac],
accessAuthRealm=@AccessAuthRealm[com.tencent.cloud.access.sso.shiro.AccessAuthRealm@1faea5],
accountService=@AccountService[com.tencent.cloud.access.account.service.impl.AccountService@197459d8],
ssoProperties=@SsoProperties[com.tencent.cloud.access.sso.config.SsoProperties@461879b2],
securityManager=@DefaultSecurityManager[org.apache.shiro.mgt.DefaultSecurityManager@3b0f92f0],
ssoService=@QCloudSsoService[com.tencent.cloud.access.sso.service.impl.QCloudSsoService@4f8704f5],
userService=@UserService[com.tencent.cloud.access.user.service.impl.UserService@5e69da74],
],
@AccessAuthPrincipal[
serialVersionUID=@Long[-2856270666386831504],
accountName=@String[qcloudAdmin],
userId=null,
accountId=@String[account-96a79v5b],
password=@String[VYUQeJrC5EJq21t/f9rb1Djm+4+eanqXY3ZkW2oiiwA=],
serviceCode=null,
isAdmin=null,
loginName=null,
serialVersionUID=@Long[8229738167949958388],
token=@String[54158a08d8104de57a855249eb6ffe06],
serialVersionUID=@Long[-4556824360581761962],
appId=null,
subAccountUin=null,
uin=null,
requestId=null,
region=null,
kv=null,
],
]
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 14:10:15; [cost=9.571541ms] result=@ArrayList[
@Object[][
@LoginRequest[com.tencent.cloud.access.sso.model.LoginRequest@3dd2bbb0],
],
@AuthenticateService[
log=@Logger[Logger[com.tencent.cloud.access.sso.service.impl.AuthenticateService]],
sessionDAO=@RedisSessionDAO[com.tencent.cloud.access.sso.shiro.RedisSessionDAO@61813e98],
accountSessionService=@AccountSessionService[com.tencent.cloud.access.account.service.impl.AccountSessionService@30e815ac],
accessAuthRealm=@AccessAuthRealm[com.tencent.cloud.access.sso.shiro.AccessAuthRealm@1faea5],
accountService=@AccountService[com.tencent.cloud.access.account.service.impl.AccountService@197459d8],
ssoProperties=@SsoProperties[com.tencent.cloud.access.sso.config.SsoProperties@461879b2],
securityManager=@DefaultSecurityManager[org.apache.shiro.mgt.DefaultSecurityManager@3b0f92f0],
ssoService=@QCloudSsoService[com.tencent.cloud.access.sso.service.impl.QCloudSsoService@4f8704f5],
userService=@UserService[com.tencent.cloud.access.user.service.impl.UserService@5e69da74],
],
@AuthenticationResponse[
serialVersionUID=@Long[-6134589862066278677],
token=@String[54158a08d8104de57a855249eb6ffe06],
accountId=@String[account-96a79v5b],
changePwd=@String[N],
users=@ArrayList[isEmpty=false;size=1],
],
]
..............
watch
指令的-x
選項表示解析三個階段的物件深度,預設值為 1,也就是隻解析到物件層,不解析物件的下一級屬性等資訊。
通過上述指令,我們獲取到了更加詳細的入參、this物件、返回值的資訊,依次解析如下:
params 方法入參:
- @String[qcloudAdmin]: 引數一,使用者名稱
- @String[Bgi8c0yC+IAvRLkuQRy6kLQ6T2J/9PNrL6G/+KX9ppE=]: 密碼加密串
- @String[127.0.0.1]: 來源主機資訊
this
方法體內部物件:
- log=@Logger: 定義 Logger 物件
- sessionDAO=@RedisSessionDAO: 會話session資料入口,為 RedisSessionDAO 物件
- accountSessionService=@AccountSessionService: 私有物件
- ........
returnObj
返回值物件,這裡為@AccessAuthPrincipal
物件:
- serialVersionUID: 使用者UID
- accountName: 登入使用者名稱
- password: 使用者密碼加密串
- token: token串
- ........
條件表示式過濾
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login '{params[0]=qcloudAdmin,returnObj}' -x 2
診斷返回資訊包含params[0]
和returnObj物件
,而且僅獲取入參params[0] == "qcloudAdmin"
的方法呼叫,最後解析深度為 2。
只有滿足條件的呼叫,才會被 Arthas 捕獲到。
觀察異常資訊
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login '{params[0],throwExp}' -e -x 2
- -e: 表示在丟擲異常之後觀察
- express觀察表示式第二個引數
throwExp
: 表示異常資訊的變數是throwExp
按方法執行耗時進行過濾
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login '{params[0],returnObj}' '#cost>200' -x 2
watch
指令的第四個引數 condition-express 為#cost>200
,表示診斷處理耗時大於 200ms 才會被捕獲輸出。-x 2
: 解析深度為 2。
僅觀察當前物件的屬性
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login 'target' -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 76 ms, listenerId: 23
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 14:48:33; [cost=3.189525ms] result=@AuthenticateService[
log=@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.tencent.cloud.access.sso.service.impl.AuthenticateService],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.tencent.cloud.access.sso.service.impl],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[Logger[com.tencent.cloud.access.sso.service]],
childrenList=@CopyOnWriteArrayList[isEmpty=false;size=2],
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[
DEFAULT_PACKAGING_DATA=@Boolean[false],
root=@Logger[Logger[ROOT]],
size=@Integer[501],
noAppenderWarning=@Integer[0],
loggerContextListenerList=@ArrayList[isEmpty=false;size=1],
loggerCache=@ConcurrentHashMap[isEmpty=false;size=501],
loggerContextRemoteView=@LoggerContextVO[LoggerContextVO{name='default', propertyMap={}, birthTime=1630634095948}],
turboFilterList=@TurboFilterList[isEmpty=true;size=0],
packagingDataEnabled=@Boolean[false],
maxCallerDataDepth=@Integer[8],
resetCount=@Integer[2],
frameworkPackages=@ArrayList[isEmpty=true;size=0],
birthTime=@Long[1630634095948],
name=@String[default],
sm=@BasicStatusManager[ch.qos.logback.core.BasicStatusManager@612c57fb],
propertyMap=@HashMap[isEmpty=true;size=0],
objectMap=@HashMap[isEmpty=false;size=6],
configurationLock=@LogbackLock[ch.qos.logback.core.spi.LogbackLock@36566db5],
scheduledExecutorService=null,
scheduledFutures=@ArrayList[isEmpty=true;size=0],
lifeCycleManager=@LifeCycleManager[ch.qos.logback.core.LifeCycleManager@44477e6],
started=@Boolean[false],
],
],
sessionDAO=@RedisSessionDAO[
.............
擴充套件思維,我們可以直接透過一次呼叫,觀察到底層連線 jdbc 的資訊:
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.AuthenticateService login 'target.userService.userDao.jdbcTemplate.dataSource.pool.poolProperties.url' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 69 ms, listenerId: 34
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 15:09:55; [cost=2.682966ms] result=@String[jdbc:mysql://*.*.*.*:3306/access_auth?useSSL=false&characterEncoding=utf8]
method=com.tencent.cloud.access.sso.service.impl.AuthenticateService.login location=AtExit
ts=2021-09-03 15:09:55; [cost=21.373065ms] result=@String[jdbc:mysql://*.*.*.*:3306/access_auth?useSSL=false&characterEncoding=utf8]
這裡就從頂層往下,獲取到了該次呼叫,涉及到查庫的 jdbc dataSource
連線配置資訊。
result
返回的是一個 String
型別物件,值為 jdbc:mysql://*.*.*.*:3306/access_auth?useSSL=false&characterEncoding=utf8
。
排除指定的類
[arthas@5201]$ watch com.tencent.cloud.access.sso.service.impl.* * 'target' -x 1 --exclude-class-pattern AuthorizeService | grep --color AuthorizeService
Press Q or Ctrl+C to abort.
--exclude-class-pattern
:排除指定的類
Trace 指令 ⭐
方法內部呼叫路徑,並輸出方法路徑上的每個節點上耗時
trace
命令能主動搜尋 class-pattern
/method-pattern
對應的方法呼叫路徑,渲染和統計整個呼叫鏈路上的所有效能開銷和追蹤呼叫鏈路
引數說明
引數名稱 | 引數說明 |
---|---|
class-pattern | 類名錶達式匹配 |
method-pattern | 方法名錶達式匹配 |
condition-express | 條件表示式 |
[E] | 開啟正規表示式匹配,預設為萬用字元匹配 |
[n:] |
命令執行次數 |
#cost |
方法執行耗時 |
這裡重點要說明的是觀察表示式,觀察表示式的構成主要由 #OGNL
表示式組成,所以你可以這樣寫"{params,returnObj}"
,只要是一個合法的 ognl 表示式,都能被正常支援。
觀察的維度也比較多,主要體現在引數 advice
的資料結構上。Advice
引數最主要是封裝了通知節點的所有資訊。
請參考表示式核心變數中關於該節點的描述。
- 特殊用法請參考:https://github.com/alibaba/arthas/issues/71
- OGNL表示式官網:https://commons.apache.org/proper/commons-ognl/language-guide.html
很多時候我們只想看到某個方法的rt大於某個時間之後的trace結果,現在Arthas可以按照方法執行的耗時來進行過濾了,例如trace *StringUtils isBlank '#cost>100'
表示當執行時間超過100ms的時候,才會輸出trace的結果。
watch/stack/trace這個三個命令都支援
#cost
使用舉例:
[arthas@5201]$ trace com.tencent.cloud.access.sso.service.impl.AuthenticateService login
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 114 ms, listenerId: 49
`---ts=2021-09-03 15:37:52;thread_name=http-nio-7001-exec-5;id=18;is_daemon=true;priority=5;TCCL=org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1cfd053
`---[6.69059ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:login()
+---[0.045058ms] com.tencent.cloud.access.sso.model.LoginRequest:getOpt() #87
+---[0.011503ms] com.tencent.cloud.access.sso.constant.LoginType:getType() #88
+---[0.004858ms] com.tencent.cloud.access.sso.constant.LoginType:getType() #89
+---[0.005082ms] com.tencent.cloud.access.sso.model.LoginRequest:getAccountName() #93
+---[0.005074ms] com.tencent.cloud.access.sso.model.LoginRequest:getPassword() #94
+---[min=0.002257ms,max=0.010395ms,total=0.012652ms,count=2] org.springframework.util.StringUtils:isEmpty() #95
+---[0.008128ms] com.tencent.cloud.access.sso.config.SsoProperties:isPasswordTextPrintable() #100
+---[0.084201ms] org.slf4j.Logger:info() #99
+---[0.00653ms] com.tencent.cloud.access.sso.model.AuthenticationResponse:<init>() #101
+---[0.004871ms] com.tencent.cloud.access.sso.model.LoginRequest:getRemoteHost() #102
+---[3.317607ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:login() #102
| `---[3.285177ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:login()
| +---[0.008045ms] org.apache.shiro.authc.UsernamePasswordToken:<init>() #139
| +---[0.011232ms] org.apache.shiro.subject.SimplePrincipalCollection:<init>() #141
| +---[0.00843ms] org.apache.shiro.subject.support.DelegatingSubject:<init>() #142
| +---[0.015667ms] org.apache.shiro.util.ThreadContext:bind() #143
| +---[1.051658ms] org.apache.shiro.subject.support.DelegatingSubject:login() #144
| +---[0.988623ms] org.apache.shiro.subject.support.DelegatingSubject:getSession() #145
| +---[0.015629ms] org.apache.shiro.session.Session:getId() #146
| +---[0.323618ms] org.apache.shiro.subject.support.DelegatingSubject:getPrincipal() #147
| +---[0.009258ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:setToken() #149
| +---[0.007608ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:setAccountName() #150
| +---[0.429798ms] org.apache.shiro.session.Session:setAttribute() #151
| `---[0.207347ms] com.tencent.cloud.access.account.service.IAccountSessionService:bind() #152
+---[0.010654ms] com.tencent.cloud.access.account.Account:<init>() #103
+---[0.824315ms] com.tencent.cloud.access.account.service.IAccountService:find() #103
+---[0.006474ms] com.tencent.cloud.access.account.Account:getLock() #104
+---[0.004144ms] com.tencent.cloud.access.account.Account:getChangePassword() #107
+---[0.005663ms] com.tencent.cloud.access.sso.model.AuthenticationResponse:setChangePwd() #107
+---[0.004683ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:getToken() #108
+---[0.00414ms] com.tencent.cloud.access.sso.model.AuthenticationResponse:setToken() #108
+---[0.003733ms] com.tencent.cloud.access.account.Account:getAccountId() #109
+---[0.005164ms] com.tencent.cloud.access.sso.model.AuthenticationResponse:setAccountId() #109
+---[0.002866ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:setAccountName() #110
+---[0.00399ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:getAccountId() #112
+---[0.014922ms] com.tencent.cloud.access.user.User:<init>() #112
+---[0.004781ms] com.tencent.cloud.access.user.User:setAppIsolate() #113
+---[0.83272ms] com.tencent.cloud.access.user.service.IUserService:findAccountList() #114
+---[0.006398ms] com.tencent.cloud.access.user.User:getUserId() #116
+---[0.005214ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:setUserId() #116
+---[0.00349ms] com.tencent.cloud.access.sso.model.AccessAuthPrincipal:getToken() #118
+---[0.002987ms] com.tencent.cloud.access.user.User:getUserId() #118
+---[0.887095ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:updateSession() #118
`---[0.004734ms] com.tencent.cloud.access.sso.model.AuthenticationResponse:setUsers() #120
`---ts=2021-09-03 15:37:52;thread_name=http-nio-7001-exec-1;id=14;is_daemon=true;priority=5;TCCL=org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1cfd053
`---[1.28437ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:login()
+---[0.003596ms] com.tencent.cloud.access.sso.model.LoginRequest:getOpt() #87
+---[0.006076ms] com.tencent.cloud.access.sso.constant.LoginType:getType() #88
+---[0.002865ms] com.tencent.cloud.access.sso.constant.LoginType:getType() #89
+---[0.010558ms] com.tencent.cloud.access.sso.model.LoginRequest:getAccessToken() #123
+---[0.003959ms] com.tencent.cloud.access.sso.model.LoginRequest:getUid() #124
+---[0.003368ms] org.springframework.util.StringUtils:isEmpty() #125
+---[0.002671ms] org.springframework.util.StringUtils:isEmpty() #128
`---[1.166953ms] com.tencent.cloud.access.sso.service.impl.AuthenticateService:updateSession() #131
耗時過濾診斷
[arthas@5201]$ trace com.tencent.cloud.access.sso.service.impl.AuthenticateService login '#cost > 2000'
#cost > 2000
: 僅捕獲開銷時間大於 2000ms 的路徑。
僅過濾方法一次呼叫
[arthas@5201]$ trace com.tencent.cloud.access.sso.service.impl.AuthenticateService login -n 1
僅捕獲一次指定方法的呼叫,然後退出任務。
sysprop 指令 -- 獲取/設定程式系統屬性
sysprop 主要用來檢視、設定當前程式的系統屬性資訊。
使用舉例
檢視當前java程式的系統屬性
[arthas@27878]$ sysprop
KEY VALUE
-------------------------------------------------------------------------
awt.toolkit sun.awt.X11.XToolkit
file.encoding.pkg sun.io
java.specification.version 1.8
sun.cpu.isalist
sun.jnu.encoding UTF-8
java.class.path /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib/tsf-ratelimit-1.29.1.jar
java.vm.vendor Tencent
sun.arch.data.model 64
java.vendor.url http://jdk.oa.com/
catalina.useNaming false
user.timezone Asia/Shanghai
org.jboss.logging.provider slf4j
os.name Linux
java.vm.specification.version 1.8
@appId tsf-ratelimit
user.country US
sun.java.launcher SUN_STANDARD
sun.boot.library.path /data/TencentKona-8.0.2-252/jre/lib/amd64
sun.java.command /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib/tsf-ratelimit-1.29.1.jar
sun.cpu.endian little
user.home /root
user.language en
java.specification.vendor Oracle Corporation
java.home /data/TencentKona-8.0.2-252/jre
file.separator /
line.separator
java.vm.specification.vendor Oracle Corporation
java.specification.name Java Platform API Specification
java.awt.graphicsenv sun.awt.X11GraphicsEnvironment
java.awt.headless true
LOG_LEVEL_PATTERN %5p [bootstrap,%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]
sun.boot.class.path /data/TencentKona-8.0.2-252/jre/lib/resources.jar:/data/TencentKona-8.0.2-252/jre/lib/rt.jar:/data/TencentKona-8.0.2-252/jre/lib/sunrsasign.jar:/data/TencentKona-8.0.2-252/jre/lib/jsse.jar:/data/TencentKona-8.0.2-2
52/jre/lib/jce.jar:/data/TencentKona-8.0.2-252/jre/lib/charsets.jar:/data/TencentKona-8.0.2-252/jre/lib/jfr.jar:/data/TencentKona-8.0.2-252/jre/classes
java.protocol.handler.pkgs org.springframework.boot.loader
sun.management.compiler HotSpot 64-Bit Tiered Compilers
java.runtime.version 1.8.0_252-b1
java.net.preferIPv4Stack true
user.name root
path.separator :
os.version 3.10.0-1127.19.1.el7.x86_64
java.endorsed.dirs /data/TencentKona-8.0.2-252/jre/lib/endorsed
java.runtime.name OpenJDK Runtime Environment
file.encoding UTF-8
spring.beaninfo.ignore true
sun.nio.ch.bugLevel
java.vm.name OpenJDK 64-Bit Server VM
LOG_FILE /var/log/tsf-oss/tsf-ratelimit/tsf-ratelimit
java.vendor.url.bug http://ce.oa.com/bia
java.io.tmpdir /tmp
catalina.home /tmp/tomcat.8220305148167761737.23000
java.version 1.8.0_252
user.dir /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1
os.arch amd64
PID 27878
java.vm.specification.name Java Virtual Machine Specification
java.awt.printerjob sun.print.PSPrinterJob
sun.os.patch.level unknown
catalina.base /tmp/tomcat.8220305148167761737.23000
loader.path /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/config
java.library.path /data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.vm.info mixed mode, sharing
java.vendor Tencent
java.vm.version 25.252-b1
java.ext.dirs /data/TencentKona-8.0.2-252/jre/lib/ext:/usr/java/packages/lib/ext
sun.io.unicode.encoding UnicodeLittle
java.class.version 52.0
臨時設定當前程式的系統屬性
[arthas@29749]$ sysprop java.class.path /data/jdk/latest
Successfully changed the system property.
KEY VALUE
-----------------------------------------------------------------------------------
java.class.path /data/jdk/latest
logger 指令 -- *檢視or設定logger
引數說明
[arthas@29749]$ logger -h
USAGE:
logger [-c <value>] [--classLoaderClass <value>] [-h] [--include-no-appender] [-l <value>] [-n <value>]
SUMMARY:
Print logger info, and update the logger level
Examples:
logger
logger -c 327a647b
logger -c 327a647b --name ROOT --level debug
logger --include-no-appender
WIKI:
https://arthas.aliyun.com/doc/logger
OPTIONS:
-c, --classloader <value> classLoader hashcode, if no value is set, default value is SystemClassLoader
--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 的 ROOT appender 的日誌級別
##### 獲取 logger 類資訊
[arthas@29749]$ logger
name ROOT
class ch.qos.logback.classic.Logger
classLoader org.springframework.boot.loader.LaunchedURLClassLoader@5674cd4d
classLoaderHash 5674cd4d
level INFO
effectiveLevel INFO
......................
##### 設定 ROOT 名稱日誌級別為 DEBUG
[arthas@29749]$ logger -c 5674cd4d -n ROOT -l DEBUG
heapdump 指令 -- 堆轉儲
引數說明
[arthas@29749]$ heapdump -h
USAGE:
heapdump [-h] [-l] [file]
SUMMARY:
Heap dump
Examples:
heapdump ## hprof 檔案儲存到當前目錄下
heapdump --live ## 活躍物件
heapdump --live /tmp/dump.hprof
WIKI:
https://arthas.aliyun.com/doc/heapdump
OPTIONS:
-h, --help this help
-l, --live Dump only live objects; if not specified, all objects in the heap are dumped.
<file> Output file
sc 指令 -- 獲取已載入類列表
引數說明
[arthas@29749]$ sc -h
USAGE:
sc [-c <value>] [--classLoaderClass <value>] [-d] [-x <value>] [-f] [-h] [-n <value>] [-E] class-pattern
SUMMARY:
Search all the classes loaded by JVM
EXAMPLES:
sc -d org.apache.commons.lang.StringUtils
sc -d org/apache/commons/lang/StringUtils
sc -d *StringUtils
sc -d -f org.apache.commons.lang.StringUtils
sc -E org\\.apache\\.commons\\.lang\\.StringUtils
WIKI:
https://arthas.aliyun.com/doc/sc
OPTIONS:
-c, --classloader <value> The hash code of the special class's classLoader
--classLoaderClass <value> The class name of the special class's classLoader.
-d, --details Display the details of class
-x, --expand <value> Expand level of object (0 by default)
-f, --field Display all the member variables
-h, --help this help
-n, --limits <value> Maximum number of matching classes with details (100 by default)
-E, --regex Enable regular expression to match (wildcard matching by default)
<class-pattern> Class name pattern, use either '.' or '/' as separator
使用舉例
#### 根據萬用字元獲取已載入的包名類名列表
[arthas@29749]$ sc com.tencent.tsf.*
com.sun.proxy.$Proxy132
com.sun.proxy.$Proxy143
com.tencent.tsf.TsfApplicationStarter
com.tencent.tsf.TsfApplicationStarter$$EnhancerBySpringCGLIB$$e6e6d3dc
com.tencent.tsf.common.TsfBaseEntity
com.tencent.tsf.common.TsfPage
com.tencent.tsf.common.TsfPageQuery
com.tencent.tsf.common.aop.ControllerCommonLog
..............
-d
引數獲取具體類的基礎資訊:
[arthas@29749]$ sc com.tencent.tsf.TsfApplicationStarter -d
class-info com.tencent.tsf.TsfApplicationStarter
code-source file:/data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib/tsf-ratelimit-1.29.1.jar!/BOOT-INF/lib/tsf-common-1.29.1.jar!/
name com.tencent.tsf.TsfApplicationStarter
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name TsfApplicationStarter
modifier public
annotation org.springframework.boot.autoconfigure.SpringBootApplication,org.springframework.cloud.client.discovery.EnableDiscoveryClient,org.springframework.cloud.netflix.feign.EnableFeignClients,org.springframework.transaction.annotation.EnableTransactionManag
ement,org.springframework.scheduling.annotation.EnableScheduling,org.springframework.context.annotation.EnableAspectJAutoProxy
interfaces
super-class +-java.lang.Object
class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@5674cd4d
+-sun.misc.Launcher$AppClassLoader@70dea4e
+-sun.misc.Launcher$ExtClassLoader@65e2dbf3
classLoaderHash 5674cd4d
class-info com.tencent.tsf.TsfApplicationStarter$$EnhancerBySpringCGLIB$$e6e6d3dc
code-source file:/data/tsf/tsf-oss/tsf-ratelimit/tsf-ratelimit-1.29.1/lib/tsf-ratelimit-1.29.1.jar!/BOOT-INF/lib/tsf-common-1.29.1.jar!/
name com.tencent.tsf.TsfApplicationStarter$$EnhancerBySpringCGLIB$$e6e6d3dc
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name TsfApplicationStarter$$EnhancerBySpringCGLIB$$e6e6d3dc
modifier public
annotation
interfaces org.springframework.context.annotation.ConfigurationClassEnhancer$EnhancedConfiguration
super-class +-com.tencent.tsf.TsfApplicationStarter
+-java.lang.Object
class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@5674cd4d
+-sun.misc.Launcher$AppClassLoader@70dea4e
+-sun.misc.Launcher$ExtClassLoader@65e2dbf3
classLoaderHash 5674cd4d
Affect(row-cnt:2) cost in 17 ms.
sm 指令 -- 獲取指定類的method資訊
該指令引數與 sc 指令引數類似。
使用舉例:
## 獲取 com.tencent.tsf.common.TsfPageQuery 類的所有方法列表
[arthas@29749]$ sm com.tencent.tsf.common.TsfPageQuery *
com.tencent.tsf.ratelimit.domain.Ratelimit <init>(Lcom/tencent/tsf/ratelimit/domain/Ratelimit;)V
com.tencent.tsf.ratelimit.domain.Ratelimit <init>()V
com.tencent.tsf.ratelimit.domain.Ratelimit toString()Ljava/lang/String;
com.tencent.tsf.ratelimit.domain.Ratelimit getRules()Ljava/util/List;
com.tencent.tsf.ratelimit.domain.Ratelimit lambda$containsIn$0(Lcom/tencent/tsf/ratelimit/domain/Ratelimit$Rule;Lcom/tencent/tsf/ratelimit/domain/Ratelimit$Rule;)Z
com.tencent.tsf.ratelimit.domain.Ratelimit setRules(Ljava/util/List;)V
com.tencent.tsf.ratelimit.domain.Ratelimit isValidRequest(Z)Z
com.tencent.tsf.ratelimit.domain.Ratelimit getRequestIdentity()Ljava/lang/String;
com.tencent.tsf.ratelimit.domain.Ratelimit setNamespaceId(Ljava/lang/String;)V
com.tencent.tsf.ratelimit.domain.Ratelimit containsIn(Ljava/util/List;)Z
com.tencent.tsf.ratelimit.domain.Ratelimit isDimensionConflict(Ljava/util/List;)Z
com.tencent.tsf.ratelimit.domain.Ratelimit getNamespaceId()Ljava/lang/String;
com.tencent.tsf.ratelimit.domain.Ratelimit getServiceName()Ljava/lang/String;
com.tencent.tsf.ratelimit.domain.Ratelimit setServiceName(Ljava/lang/String;)V
com.tencent.tsf.common.proxy.Application <init>()V
com.tencent.tsf.common.proxy.Application setApplicationId(Ljava/lang/String;)V
com.tencent.tsf.common.proxy.Application getMicroserviceType()Ljava/lang/String;
com.tencent.tsf.common.proxy.Application setMicroserviceType(Ljava/lang/String;)V
com.tencent.tsf.common.proxy.Application getApplicationId()Ljava/lang/String;
com.tencent.tsf.ratelimit.proxy.Microservice <init>()V
com.tencent.tsf.ratelimit.proxy.Microservice setMicroserviceName(Ljava/lang/String;)V
com.tencent.tsf.ratelimit.proxy.Microservice setNamespaceId(Ljava/lang/String;)V
com.tencent.tsf.ratelimit.proxy.Microservice getMicroserviceName()Ljava/lang/String;
com.tencent.tsf.ratelimit.proxy.Microservice getNamespaceId()Ljava/lang/String;
com.tencent.tsf.ratelimit.proxy.Microservice getMicroserviceId()Ljava/lang/String;
com.tencent.tsf.ratelimit.proxy.Microservice setMicroserviceId(Ljava/lang/String;)V
com.tencent.tsf.common.TsfPageQuery <init>()V
com.tencent.tsf.common.TsfPageQuery clear()V
com.tencent.tsf.common.TsfPageQuery getOffset()Ljava/lang/Integer;
com.tencent.tsf.common.TsfPageQuery setOffset(Ljava/lang/Integer;)V
com.tencent.tsf.common.TsfPageQuery initDefault()V
com.tencent.tsf.common.TsfPageQuery setSearchWord(Ljava/lang/String;)V
com.tencent.tsf.common.TsfPageQuery getOrderType()Ljava/lang/Integer;
com.tencent.tsf.common.TsfPageQuery getOrderTypeStr()Ljava/lang/String;
com.tencent.tsf.common.TsfPageQuery setOrderType(Ljava/lang/Integer;)V
com.tencent.tsf.common.TsfPageQuery getOrderBy()Ljava/lang/String;
com.tencent.tsf.common.TsfPageQuery setOrderBy(Ljava/lang/String;)V
com.tencent.tsf.common.TsfPageQuery getRealPage()I
com.tencent.tsf.common.TsfPageQuery transerPageQuery(Lcom/tencent/tsf/common/TsfPageQuery;)V
com.tencent.tsf.common.TsfPageQuery getSearchWordLikeStr()Ljava/lang/String;
com.tencent.tsf.common.TsfPageQuery getLimit()Ljava/lang/Integer;
com.tencent.tsf.common.TsfPageQuery setLimit(Ljava/lang/Integer;)V
com.tencent.tsf.common.TsfPageQuery getSearchWord()Ljava/lang/String;
Affect(row-cnt:43) cost in 12 ms.
monitor 指令 -- 方法執行監控
該指令為非實時返回指令,預設 120s 返回一次統計值。
統計區間時間段內,方法執行的總數、成功次數、失敗次數、平均執行率、失敗比例 等資訊。
引數說明
[arthas@8738]$ monitor -h
USAGE:
monitor [-b] [-c <value>] [--exclude-class-pattern <value>] [-h] [-n <value>] [--listenerId <value>] [-E <value>] [-v] class-pattern method-pattern [condition-express]
SUMMARY:
Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
Examples:
monitor org.apache.commons.lang.StringUtils isBlank
monitor org.apache.commons.lang.StringUtils isBlank -c 5
monitor org.apache.commons.lang.StringUtils isBlank params[0]!=null
monitor -b org.apache.commons.lang.StringUtils isBlank params[0]!=null
monitor -E org\.apache\.commons\.lang\.StringUtils isBlank
WIKI:
https://arthas.aliyun.com/doc/monitor
OPTIONS:
-b, --before Evaluate the condition-express before method invoke
-c, --cycle <value> The monitor interval (in seconds), 60 seconds by default
--exclude-class-pattern <value> exclude class name pattern, use either '.' or '/' as separator
-h, --help this help
-n, --limits <value> Threshold of execution times
--listenerId <value> The special listenerId
-E, --regex <value> Enable regular expression to match (wildcard matching by default)
-v, --verbose Enables print verbose information, default value false.
<class-pattern> Path and classname of Pattern Matching
<method-pattern> Method of Pattern Matching
<condition-express> Conditional expression in ognl style, for example:
TRUE : 1==1
TRUE : true
FALSE : false
TRUE : 'params.length>=0'
FALSE : 1==2
'#cost>100'
使用舉例
[arthas@8738]$ monitor com.tencent.tsf.resource.ns.dao.NamespaceDao *
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 15) cost in 104 ms, listenerId: 6
timestamp class method total success fail avg-rt(ms) fail-rate
----------------------------------------------------------------------------------------------------------------------------------------------------
2021-09-09 18:26:58 com.tencent.tsf.resource.ns.dao.NamespaceDao countList 12 12 0 1.08 0.00%
2021-09-09 18:26:58 com.tencent.tsf.resource.ns.dao.NamespaceDao getAuthWhereClause 28 28 0 0.18 0.00%
2021-09-09 18:26:58 com.tencent.tsf.resource.ns.dao.NamespaceDao findList 2 2 0 1.09 0.00%