引言
這里記錄一下我在使用 arthas 排查現場問題時, 使用的幾個主要命令, 怕自己忘了, 寫下來到時候可以參考.
我的個人博客:我心永恆
原文地址:arthas 使用總結
查看類加載的信息
sc -d <ClassName>
參數名稱 | 參數說明 |
---|---|
class-pattern | 類名表達式匹配 |
method-pattern | 方法名表達式匹配 |
[d] | 輸出當前類的詳細信息, 包括這個類所加載的原始文件來源, 類的聲明, 加載的 ClassLoader 等詳細信息. 如果一個類被多個 ClassLoader 所加載, 則會出現多次 |
[E] | 開啟正則表達式匹配, 默認為通配符匹配 |
[f] | 輸出當前類的成員變量信息 (需要配合參數-d 一起使用) |
[x:] | 指定輸出靜態變量時屬性的遍歷深度, 默認為 0, 即直接使用 toString 輸出 |
[c:] |
指定 class 的 ClassLoader 的 hashcode |
[classLoaderClass:] |
指定執行表達式的 ClassLoader 的 class name |
[n:] |
具有詳細信息的匹配類的最大數量 (默認為 100) |
# 模糊搜索
sc demo.*
# 打印類的詳細信息
sc -d demo.MathGame
# 打印出類的 Field 信息
sc -d -f demo.MathGame
查看類的靜態變量
# 查看類的靜態變量 getstatic ${類名} ${屬性名}
getstatic cn.lw.ClassName propName
注意 hashcode 是變化的, 需要先查看當前的 ClassLoader 信息, 使用 sc -d <ClassName>
提取對應 ClassLoader 的 hashcode. 指定 classLoader 注意 hashcode 是變化的, 需要先查看當前的 ClassLoader 信息, 使用 sc -d <ClassName>
提取對應 ClassLoader 的 hashcode. 如果你使用 -c
, 你需要手動輸入 hashcode:-c <hashcode>
getstatic -c 3d4eac69 demo.MathGame random
對於只有唯一實例的 ClassLoader 可以通過--classLoaderClass 指定 class name, 使用起來更加方便:
getstatic --classLoaderClass sun.misc.Launcher$AppClassLoader demo.MathGame random
注: 這里 classLoaderClass 在 java 8 是 sun.misc.Launcher$AppClassLoader
, 而 java 11 的 classloader 是 jdk.internal.loader.ClassLoaders$AppClassLoader
. --classLoaderClass
的值是 ClassLoader 的類名, 只有匹配到唯一的 ClassLoader 實例時才能工作, 目的是方便輸入通用命令, 而 -c <hashcode>
是動態變化的. 如果該靜態屬性是一個復雜對象, 還可以支持在該屬性上通過 ognl
表示進行遍歷, 過濾, 訪問對象的內部屬性等操作.
查看線上代碼
jad cn.com.xxx
攔截方法的入參和出參 獲取 Spring 中的 bean 查看配置參數
記錄方法調用的信息
tt 命令的文檔在此:https://arthas.aliyun.com/doc/tt.html
tt -t demo.MathGame primeFactors -n ${記錄次數} params[0].mobile==13989838402
# 跟蹤完了之后
tt -i 1003 -p # -p 不需要參數, 它的意思是重新將這個方法調用一次
獲取 Spring 中的 bean
# 先這樣搞
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 3
# 隨便訪問一個 web 接口
# 然后再這樣搞
tt -i 1000 -w 'target.getApplicationContext().getBean("rocketMQConsumerManagerImpl")'
tt -i 1000 -w 'target.getApplicationContext().getBean("rocketMQConsumerManagerImpl").getTargetSource()'
tt -i 1000 -w 'target.getApplicationContext().getBean("rocketMQConsumerManagerImpl").getTargetSource().target'
P.S. 不好意思, "rocketMQConsumerManagerImpl"
這里需要加引號, 不然會報找不到.
參考:https://blog.csdn.net/yunqiinsight/article/details/86710798
查看方法調用棧
# 方法調用棧
stack org.slf4j.Logger warn params[1].indexOf('roadblockindex.bin')>-1 -x 3 -n 2
arthas 調用類的靜態方法
方法就是使用 ognl 表達式即可:
ognl -c 31cefde0 '@com.kwok.schedule.task.ESHisIndexParseTask@parse()'
問題來了, 這個 31cefde0
是個什么東東?
這個就是類加載器的 hashcode, 而這個類加載器就是加載我們執行的靜態方法的類的類加載器, 窩草, 有點繞口.
那么如何獲取這個類加載器的 hashcode 呢?
方式一: sc
命令
sc -d com.kwok.schedule.task.ESHisIndexParseTask
方式二: sm
命令
sm -d com.kwok.schedule.task.ESHisIndexParseTask parse
上面兩個命令輸出的 classLoaderHash
就是我們要獲取的值.
問題來了: 如何這個類沒有被加載怎么辦?
如果返回信息:Affect(row-cnt:0)
, 則表示該類還未執行加載, 需要使用 classloader
命令加載該類后執行該類靜態方法.
由於 SpringBoot 項目 Jar 包 ClassLoader 為 org.springframework.boot.loader.LaunchedURLClassLoader, 而 Arthas 默認的是 SystemClassLoader, 在使用 Arthas 中 ognl 命令時需要指定加載目標類的 ClassLoader.
在加載器列表中找到 org.springframework.boot.loader.LaunchedURLClassLoader
加載器的 hash.
classloader -l
使用 SpringBoot 類加載器加載目標類.
classloader -c 31cefde0 --load com.kwok.schedule.task.ESHisIndexParseTask
31cefde0
就是類加載的 hash.
這一小節的內容來自:https://blog.csdn.net/guokexiaohao/article/details/106065284
Arthas 監聽輸入參數是否包含某一字符串
監聽 com.demo.cloud.jpa.util.JPAUtil
類中的 executeNativeQuery
方法,ognl 條件參數: 只檢測包含 base_point 字符串的輸入
watch com.demo.cloud.jpa.util.JPAUtil executeNativeQuery {params} params[0].indexOf(\'base_point\')>-1 -x 3`
tt -t cn.com.xxx.base.tools.RedisUtils getStringValue params[0].indexOf('cfg:VIDEO_CALL_RONGYUN_SERVER_ADDRESS')>-1 -x 3 -n 100
'xxx:cfg:VIDEO_CALL_RONGYUN_SERVER_ADDRESS'
參考
我的個人博客:我心永恆
原文地址:arthas 使用總結