常見Arthas命令與實踐

Arthas 官網:https://arthas.aliyun.com/doc/,官方文檔對 Arthas 的每個命令都做出了介紹和解釋,并且還有在線教程,方便學習和熟悉命令。

圖片

Arthas Idea 的 IDEA 插件。

這是一款能快速生成 Arthas命令的插件,可快速生成可用于該類或該方法的 Arthas 命令,大大提高排查問題的效率。

圖片

常用命令

盡管 Arthas 命令眾多,但在實際使用中我們只需聚焦于那些常用命令。本文旨在重點介紹這些常用命令,并提供使用技巧和最佳實踐,幫助您更好地運用 Arthas。

類命令

getstatic

查看類的靜態屬性。推薦直接使用 ognl 命令,更加靈活。

# getstatic class_name field_name
getstatic demo.MathGame random# 如果該靜態屬性是一個復雜對象,還可以支持在該屬性上通過 ognl 表達式進行遍歷,過濾,訪問對象的內部屬性等操作。
# 例如,假設 n 是一個 Map,Map 的 Key 是一個 Enum,我們想過濾出 Map 中 Key 為某個 Enum 的值,可以寫如下命令
getstatic com.alibaba.arthas.Test n 'entrySet().iterator.{? #this.key.name()=="STOP"}'
jad

反編譯指定已加載類的源碼。jad 只能反編譯單個類,如需批量下載指定包的目錄的 class 字節碼請使用 dump 命令。

比如我們想知道自己提交的代碼是否生效了,這種場景jad 命令就特別有用。

# 反編譯 java.lang.String
jad java.lang.String
# 默認情況下,反編譯結果里會帶有 ClassLoader 信息,通過 --source-only 選項,可以只打印源代碼。方便和 mc/retransform 命令結合使用。
jad --source-only java.lang.String
# 反編譯指定的函數
jad java.lang.String substring
# 當有多個 ClassLoader 都加載了這個類時,jad 命令會輸出對應 ClassLoader 實例的 hashcode
# 然后你只需要重新執行 jad 命令,并使用參數 -c <hashcode> 就可以反編譯指定 ClassLoader 加載的那個類了
jad org.apache.log4j.Logger -c 69dcaba4
retransform

加載外部的 .class 文件,retransform jvm 已加載的類。

# 結合 jad/mc 命令使用,jad 命令反編譯,然后可以用其它編譯器,比如 vim 來修改源碼
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
# mc 命令來內存編譯修改過的代碼
mc /tmp/UserController.java -d /tmp
# 用 retransform 命令加載新的字節碼
retransform /tmp/com/example/demo/arthas/user/UserController.class

加載指定的 .class 文件,然后解析出 class name,再 retransform jvm 中已加載的對應的類。每加載一個 .class 文件,則會記錄一個 retransform entry。

如果多次執行 retransform 加載同一個 class 文件,則會有多條 retransform entry。

# 查看 retransform entry
retransform -l
# 刪除指定 retransform entry,需要指定 id:
retransform -d 1
# 刪除所有 retransform entry
retransform --deleteAll
# 顯式觸發 retransform
retransform --classPattern demo.MathGame

如果對某個類執行 retransform 之后,想消除 retransform 的影響,則需要:

  • 刪除這個類對應的 retransform entry。
  • 重新顯式觸發 retransform。

retransform 的限制:

  • 不允許新增加 field/method。
  • 正在跑的函數,沒有退出不能生效。

使用 mc 命令來編譯 jad 的反編譯的代碼有可能失敗。可以在本地修改代碼,編譯好后再上傳到服務器上。有的服務器不允許直接上傳文件,可以使用 base64 命令來繞過。

  1. 在本地先轉換 .class 文件為 base64,再保存為 result.txt。
 base64  -i /tmp/test.class -o /tmp/result.txt
  1. 到服務器上,新建并編輯 result.txt,復制本地的內容,粘貼再保存。
vim  /tmp/result.txt
  1. 把服務器上的 result.txt 還原為.class
base64 -d /tmp/result.txt > /tmp/test.class
  1. 用 md5 命令計算哈希值,校驗是否一致。
md5sum  /tmp/test.class

監測排查命令

監測排查命令是 Arthas 中最常用的命令。

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

monitor

方法執行監控。可對方法的調用次數,成功次數,失敗次數等維度進行統計。

# -b:計算條件表達式過濾統計結果(方法執行完畢之前),默認是方法執行之后過濾
# -c:統計周期,默認值為 120 秒
# params[0] <= 2:過濾條件,方法第一個參數小于等于2
monitor -b -c 5 com.test.testes.MathGame primeFactors "params[0] <= 2"
stack

輸出當前方法被調用的調用路徑。

很多時候我們都知道一個方法被執行,但這個方法被執行的路徑非常多,或者你根本就不知道這個方法是從那里被執行了,此時你需要的是 stack 命令。

# -n:執行次數
stack demo.MathGame primeFactors  -n  2
thread

查看當前線程信息,查看線程的堆棧。

# 沒有參數時,默認按照 CPU 增量時間降序排列,只顯示第一頁數據
# -i 1000: 統計最近 1000ms 內的線程 CPU 時間
# -n 3: 展示當前最忙的前 N 個線程并打印堆棧
# --state WAITING:查看指定狀態的線程
thread# 顯示指定線程的運行堆棧
thread id# 找出當前阻塞其他線程的線程,注意,目前只支持找出 synchronized 關鍵字阻塞住的線程, 如果是 java.util.concurrent.Lock 目前還不支持。
thread -b

輸出:

  • Internal 表示為 JVM 內部線程,參考 dashboard 命令的介紹。
  • cpuUsage 為采樣間隔時間內線程的 CPU 使用率,與 dashboard 命令的數據一致。
  • deltaTime 為采樣間隔時間內線程的增量 CPU 時間,小于 1ms 時被取整顯示為 0ms。
  • time 為線程運行總 CPU 時間。
trace

方法內部調用路徑,并輸出方法路徑上的每個節點上耗時。

trace 命令在定位性能問題的時候特別有用。

# -n 1:限制匹配次數
# --skipJDKMethod false:默認情況下,trace 不會包含 jdk 里的函數調用,如果希望 trace jdk 里的函數,需要顯式設置
# --exclude-class-pattern :排除掉指定的類
trace javax.servlet.Filter * -n 1 --skipJDKMethod false --exclude-class-pattern com.demo.TestFilter
# 正則表達式匹配路徑上的多個類和函數,達到多層 trace 的效果
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3

動態 tradce參考:https://arthas.aliyun.com/doc/trace.html#動態-trace

tt

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

說明:

  • tt 命令的實現是:把函數的入參/返回值等,保存到一個Map<Integer, TimeFragment>里,默認的大小是 100。
  • tt 相關功能在使用完之后,需要手動釋放內存,否則長時間可能導致 OOM。退出 arthas 不會自動清除 tt 的緩存 map。
  • 需要強調的是,tt 命令是將當前環境的對象引用保存起來,但僅僅也只能保存一個引用而已。如果方法內部對入參進行了變更,或者返回的對象經過了后續的處理,那么在 tt 查看的時候將無法看到當時最準確的值。這也是為什么 watch 命令存在的意義。
# -l:顯示tt記錄
tt -l# -s:檢索tt記錄,比如:-s 'method.name=="primeFactors"'
tt -s 'method.name=="primeFactors"'# -t:這個參數的表明希望記錄下類 *Test 的 print 方法的每次執行情況。
tt -t# 查看具體調用信息
tt -i 1003# -w:--watch-express 觀察時空隧道使用 ognl 表達式
tt -w '@demo.MathGame@random.nextInt(100)'# 重做一次調用,當我們對程序做出了修改之后,希望再次調用觀測結果,此時你需要 -p 參數
# --replay-times:指定調用次數
# --replay-interval:指定多次調用間隔(單位 ms, 默認 1000ms)
tt -i 1004 -p# 通過索引刪除指定的 tt 記錄
tt -d 1001# 清除所有的 tt 記錄
tt --delete-all

Spring MVC里獲取對于的 bean:

# 獲取Spring Context里的bean
tt -n 1 -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
watch

函數執行數據觀測,通過編寫 OGNL 表達式進行對應變量的查看。

  • watch 命令定義了 4 個觀察事件點,即 -b 函數調用前,-e 函數異常后,-s 函數返回后,-f 函數結束后。
  • 4 個觀察事件點 -b-e-s 默認關閉,-f 默認打開,當指定觀察點被打開后,在相應事件點會對觀察表達式進行求值并輸出。
  • 這里要注意函數入參函數出參的區別,有可能在中間被修改導致前后不一致,除了 -b 事件點 params 代表函數入參外,其余事件都代表函數出參。
  • 當使用 -b 時,由于觀察事件點是在函數調用前,此時返回值或異常均不存在。
  • 在 watch 命令的結果里,會打印出location信息。location有三種可能值:AtEnterAtExitAtExceptionExit。對應函數入口,函數正常 return,函數拋出異常。
 # -x表示遍歷深度,可以調整來打印具體的參數和結果內容,默認值是 1。# -x最大值是 4,防止展開結果占用太多內存。用戶可以在ognl表達式里指定更具體的 field。watch demo.MathGame primeFactors -x 3# 可以使用ognl表達式進行條件過濾watch demo.MathGame primeFactors "{params[0],target}" "params[0]<0" "#cost>200"# 可以使用 target.field_name 訪問當前對象的某個屬性watch demo.MathGame primeFactors 'target.illegalArgumentCount'#  watch 構造函數watch demo.MathGame <init> '{params,returnObj,throwExp}' -v# watch內部類watch OuterClass$InnerClass

JVM命令

heapdump

生成堆轉儲文件。

# dump 到指定文件
heapdump arthas-output/dump.hprof
# 只 dump live 對象
heapdump --live /tmp/dump.hprof
jfr

Java Flight Recorder (JFR) 是一種用于收集有關正在運行的 Java 應用程序的診斷和分析數據的工具。

它集成到 Java 虛擬機 (JVM) 中,幾乎不會造成性能開銷,因此即使在負載較重的生產環境中也可以使用。

# 啟動 JFR 記錄
jfr start# 啟動 jfr 記錄,指定記錄名,記錄持續時間,記錄文件保存路徑。
# --duration  JFR 記錄持續時間,支持單位配置,60s, 2m, 5h, 3d,不帶單位就是秒,默認一直記錄。
jfr start -n myRecording --duration 60s -f /tmp/myRecording.jfr# 查看所有 JFR 記錄信息
jfr status# 查看指定記錄 id 的記錄信息
jfr status -r 1# 查看指定狀態的記錄信息
jfr status --state closed# jfr dump 會輸出從開始到運行該命令這段時間內的記錄到 JFR 文件,且不會停止 jfr 的記錄
# 生成的結果可以用支持 jfr 格式的工具來查看。比如:JDK Mission Control : https://github.com/openjdk/jmc
jfr dump -r 1 -f /tmp/myRecording1.jfr# 停止 jfr 記錄
jfr stop -r 1
memory

查看 JVM 內存信息。

輸出如下:

Memory                           used      total      max        usage
heap                             32M       256M       4096M      0.79%
g1_eden_space                    11M       68M        -1         16.18%
g1_old_gen                       17M       184M       4096M      0.43%
g1_survivor_space                4M        4M         -1         100.00%
nonheap                          35M       39M        -1         89.55%
codeheap_'non-nmethods'          1M        2M         5M         20.53%
metaspace                        26M       27M        -1         96.88%
codeheap_'profiled_nmethods'     4M        4M         117M       3.57%
compressed_class_space           2M        3M         1024M      0.29%
codeheap_'non-profiled_nmethods' 685K      2496K      120032K    0.57%
mapped                           0K        0K         -          0.00%
direct                           48M       48M        -          100.00%
dashboard

當前系統的實時數據面板,按 ctrl+c 退出。

# i:刷新實時數據的時間間隔 (ms),默認 5000m
# n:刷新實時數據的次數
dashboard -i 5000 -n 3

顯示 ID 為 -1 的是 JVM的內部線程,JVM 內部線程包括下面幾種:

  • JIT 編譯線程:如 C1 CompilerThread0, C2 CompilerThread0
  • GC 線程:如 GC Thread0, G1 Young RemSet Sampling。
  • 其它內部線程:如 VM Periodic Task Thread, VM Thread, Service Thread。

當 JVM 堆(heap)/元數據(metaspace) 空間不足或 OOM 時, GC 線程的 CPU 占用率會明顯高于其他的線程。

classloader

classloader 命令將 JVM 中所有的 classloader 的信息統計出來,并可以展示繼承樹,urls 等。

# 按類加載類型查看統計信息
classloader# 按類加載實例查看統計信息
classloader -l# 查看 ClassLoader 的繼承樹
classloader -t# 查看 URLClassLoader 實際的 urls,通過 classloader -l 可以獲取到哈希值
classloader -c 3d4eac69
logger

查看 logger 信息,更新 logger level。

# 查看所有 logger 信息
logger# 查看指定名字的 logger 信息
logger -n org.springframework.web# 更新 logger level
logger --name ROOT --level debug
sc

查看 JVM 已加載的類信息。

# 模糊搜索
sc demo.*# 打印類的詳細信息
sc -d demo.MathGame# 打印出類的 Field 信息
sc -d -f demo.MathGame
mbean

查看 Mbean 的信息。

所謂 MBean 就是托管的Java對象,類似于 JavaBeans 組件,遵循 JMX(Java Management Extensions,即Java管理擴展) 規范中規定的設計模式。

MBean可以表示任何需要管理的資源。

# 列出所有 Mbean 的名稱
mbean# 查看 Mbean 的元信息
mbean -m java.lang:type=Threading# 查看 mbean 屬性信息,mbean 的 name 支持通配符匹配 mbean java.lang:type=Th*
mbean java.lang:type=Threading#通配符匹配特定的屬性字段
mbean java.lang:type=Threading *Count# 實時監控使用-i,使用-n命令執行命令的次數(默認為 100 次)
mbean -i 1000 -n 50 java.lang:type=Threading *Count

比如我們可以使用 mbean 命令來查看 Druid 連接池的屬性:

mbean com.alibaba.druid.pool:name=dataSource,type=DruidDataSource
profiler

生成應用熱點的火焰圖。本質上是通過不斷的采樣,然后把收集到的采樣結果生成火焰圖。

# 啟動 profiler
# 生成的是 cpu 的火焰圖,即 event 為cpu。可以用--event參數來指定。
profiler start --event cpu# 獲取已采集的 sample 的數量
profiler getSamples# 查看 profiler 狀態
profiler status# 停止 profiler,生成結果,結果文件是html格式,也可以用--format參數指定
profiler stop --format html# 恢復采樣,start和resume的區別是:start是新開始采樣,resume會保留上次stop時的數據。
profiler resume# 配置 include/exclude 來過濾數據
profiler start --include 'java/*' --include 'demo/*' --exclude '*Unsafe.park*'# 生成 jfr 格式結果
profiler start --file /tmp/test.jfr
vmoption

查看,更新 VM 診斷相關的參數。

# 查看所有的 option
vmoption# 查看指定的 option
vmoption PrintGC# 更新指定的 option
vmoption PrintGC true
vmtool

vmtool 利用 JVMTI 接口,實現查詢內存對象,強制 GC 等功能。

# --limit:可以限制返回值數量,避免獲取超大數據時對 JVM 造成壓力。默認值是 10
# --action:執行的動作
vmtool --action getInstances --className java.lang.String --limit 10#強制 GC
vmtool --action forceGc# interrupt 指定線程
vmtool --action interruptThread -t 1

特殊命令

可以使用 -v 查看觀察匹配表達式的執行結果

ognl

執行 ognl 表達式,是Arthas中最為靈活的命令。

# -c:執行表達式的 ClassLoader 的 hashcode,默認值是 SystemClassLoader
# --classLoaderClass:指定執行表達式的 ClassLoader 的 class name
# -x:結果對象的展開層次,默認值 1
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @org.springframework.boot.SpringApplication@logger

有關 ognl 語法介紹,放在下文。

options

全局開關,慎用!

# 查看所有的 options
options# 設置指定的 option,默認情況下json-format為 false,如果希望watch/tt等命令結果以 json 格式輸出,則可以設置json-format為 true。
options json-format true# 默認情況下,watch/trace/tt/trace/monitor等命令不支持java.* package 下的類。可以設置unsafe為 true,則可以增強。
options unsafe true# Arthas 默認啟用strict模式,在ognl表達式里,禁止更新對象的 Property 或者調用setter函數
# 用戶如果確定要在ognl表達式里更新對象,可以執行options strict false,關閉strict模式。
options strict false

幫助命令

help

查看命令幫助信息,可以查看當前 arthas 版本支持的指令,或者查看具體指令的使用說明。

help dashboard 
或者
dashboard  -help
history

打印命令歷史。

#查看最近執行的3條指令
history 3#清空指令
history -c
cls

清空當前屏幕區域。

quit

僅退出當前的連接,Attach 到目標進程上的 arthas 還會繼續運行,端口會保持開放,下次連接時可以直接連接上。或者直接按 Q 也能退出。

stop

完全退出 arthas,stop 時會重置所有增強過的類。

reset

重置增強類,將被 Arthas 增強過的類全部還原,Arthas 服務端 stop 時會重置所有增強過的類。

# 還原指定類
reset Test# 還原所有類
reset

Advice

無論是匹配表達式也好、觀察表達式也罷,他們核心判斷變量都是圍繞著一個 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本次調用類所在的 ClassLoader
clazz本次調用類的 Class 引用
method本次調用方法反射引用
target本次調用類的實例
params本次調用參數列表,這是一個數組,如果方法是無參方法則為空數組
returnObj本次調用返回的對象。當且僅當 isReturn==true 成立時候有效,表明方法調用是以正常返回的方式結束。如果當前方法無返回值 void,則值為 null
throwExp本次調用拋出的異常。當且僅當 isThrow==true 成立時有效,表明方法調用是以拋出異常的方式結束。
isBefore輔助判斷標記,當前的通知節點有可能是在方法一開始就通知,此時 isBefore==true 成立,同時 isThrow==falseisReturn==false,因為在方法剛開始時,還無法確定方法調用將會如何結束。
isThrow輔助判斷標記,當前的方法調用以拋異常的形式結束。
isReturn輔助判斷標記,當前的方法調用以正常返回的形式結束。

所有變量都可以在表達式中直接使用,如果在表達式中編寫了不符合 OGNL 腳本語法或者引入了不在表格中的變量,則退出命令的執行。

用戶可以根據當前的異常信息修正 條件表達式觀察表達式

快捷鍵

# 自動補全,命令后敲 - 或 -- ,然后按 tab 鍵,可以展示出此命令具體的選項
Tab# 退出當前連接
Q# 后臺異步命令相關快捷鍵
ctrl + c: 終止當前命令
ctrl + z: 掛起當前命令,后續可以 bg/fg 重新支持此命令,或 kill 掉
ctrl + a: 回到行首
ctrl + e: 回到行尾

OGNL

OGNL(Object-Graph Navigation Language)是一種表達式語言(EL),簡單來說就是一種簡化了的Java屬性的取值語言,Arthas使用它做表達式過濾。

OGNL 表達式官網:https://commons.apache.org/dormant/commons-ognl/language-guide.htm

變量引用

OGNL支持用變量來保存中間結果,并在后面的代碼中再次引用它。

OGNL中的所有變量,對整個表達式都是全局可見的,引用變量的方法是在變量名之前加上 # 號,OGNL會將當前對象保存在 “this” 變量中,這個變量也可以像其他任何變量一樣引用,用 #this 表示當前對象。

這里列舉一些常用的語法:

# 調用靜態屬性
'@全路徑類目@靜態屬性名'# 調用靜態方法
'@全路徑類目@靜態方法名("參數")'# 過濾,判斷,篩選
'params[0]':查看第一個參數
'params[0].size()':查看第一個參數的size
'params[0]=="xyz"':判斷字符串相等
'params[0]==123456789L':判斷long型
'params[0].{ #this.name }':將結果按name屬性映射
'params[0].{? #this.name == null }':按條件過濾
'params[0].{? #this.age > 10 }.size()':過濾后統計
'params[0].{^ #this.name != null}':選擇第一個滿足條件
'params[0].{$ #this.name != null}':選擇最后一個滿足條件
'params[0].{? #this.age > 10 }.size().(#this > 20 ? #this - 10 : #this + 10)':子表達式求值
'name in { null,"Untitled" }':這條語句判斷name是否等于null或者 Untitled# 構造對象
'#{ "foo" : "foo value", "bar" : "bar value" }':構造map參數
'#@java.util.LinkedHashMap@{ "foo" : "foo value", "bar" : "bar value" }':構造特定類型map
'new com.Test("xiaoming",18)':構造方法,new 全路徑類名()
'new int[] { 1, 2, 3 }':創建數組并初始化# 訪問對象
'@com.Test@getPerson("xiaoming",18).name':訪問復雜對象屬性,用 .屬性名 訪問屬性
'@com.Test@getChilds({"xiaoming"})[0]':訪問List或者數組類型,用 [索引] 訪問
'@com.Test@getMap()["xiaoming"]': 訪問Map對象,用 ["key"],key要用雙引號# 臨時變量
'#value1=@com.Test@getPerson("xiaoming",18), #value2=@com.Test@setPerson(#value1) ,{#value1,#value2}': 方法A的返回值當做方法B的入參
'#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}':執行多行表達式,賦值給臨時變量,返回一個List
'#obj=new com.User("xiaoming",18),@com.Test@inputObj(#obj)':先用構造函數構造一個對象,然后把這個對象當做入參傳入

實用功能

管道

Arthas 命令后可接 grep 進行進一步篩選或操作,比如:

classloader -a | grep "String"

后臺異步執行

當需要排查一個問題,但是這個問題的出現時間不能確定,那我們就可以把檢測命令掛在后臺運行,并將保存到輸出日志。

# 比如希望執行后臺執行 trace 命令,那么調用下面命令
trace Test t &# 如果希望查看當前有哪些 arthas 任務在執行,可以執行 jobs 命令
jobs# 可通過 > 或者 >> 將任務輸出結果輸出到指定的文件中,可以和 & 一起使用,實現 arthas 命令的后臺異步任務。比如:
trace Test t >> test.out &#異步執行的命令,如果希望停止,可執行kill命令
kill <job-id># 當任務正在前臺執行,可以執行 ‘ctrl + z’ 將任務暫停。通過jbos查看任務狀態將會變為 Stopped,再通過bg <job-id>或者fg <job-id>可讓任務重新開始執行
# 可以把對應的任務轉到前臺繼續執行。在前臺執行時,無法在 console 中執行其他命令
fg <job-id>
# 可以把對應的任務在后臺繼續執行
bg <job-id>

實用技巧

#  獲取接口的響應時間
watch org.springframework.web.servlet.DispatcherServlet doService '{params[0].getRequestURI()+" "+ #cost}'  -n 5  -x 3 '#cost>100'  -f# 獲取指定header 頭的信息,比如這里 獲取 trace-idwatch org.springframework.web.servlet.DispatcherServlet doService '{params[0].getRequestURI()+"  header="+params[1].getHeaders("trace-id")}'  -n 10  -x 3 -f# 查看執行的SQL,下面兩個都可以
watch java.sql.Connection prepareStatement '{params,throwExp}'  -n 5  -x 3 
watch org.apache.ibatis.mapping.BoundSql getSql '{params,returnObj,throwExp}'  -n 5  -x 3 # 調用任意bean中的方法
# 1.先獲取 classLoaderHash
sc -d com.alibaba.dubbo.config.spring.extension.SpringExtensionFactor# 2.ognl 調用對應 bean 的方法,把 34f5090e 替換為對于的 classLoaderHash
ognl  -c 34f5090e '#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next,#context.getBean("userServiceImpl").find("小明")'# 當傳參是復雜對象時
ognl -c 34f5090e '#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next,#data=new Children(), #query=new User(),#query.setChildren(#data),#query.setRequestId("1"), #data.setName("小明"),#context.getBean("userServiceImpl").find(#query)'# vmtool 命令提供了更簡單的語法,也可以調用任意bean中的方法
vmtool --action getInstances  --className org.springframework.context.ApplicationContext --express 'instances[0].getBean("userServiceImpl").find("小明")'# 動態修改 bean 屬性值
# 本質原理就是先獲取 bean 實例,通過反射去修改對應屬性值
ognl -c 34f5090e org.ClassLoader
'#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next, #instence=#context.getBean("userServiceImpl"),#fieldObj=@com.User@class.getDeclaredField("age"),#fieldObj.setAccessible(true), #fieldObj.set(#instence,18)'# 除了 ognl 也可以通過 vmtool 去獲取 bean
vmtool --action getInstances  --className org.springframework.context.ApplicationContext --express 'instances[0].getBean("userServiceImpl")'

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66634.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66634.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66634.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mellanox ConnectX 系列網卡的雙驅動架構:以太網與 InfiniBand 的協同設計

在現代數據中心和高性能計算(HPC)環境中,網絡硬件的性能和功能至關重要。Mellanox ConnectX 系列網卡以其卓越的性能和多功能性而聞名,支持從傳統的以太網到高性能的 InfiniBand 網絡協議。這種多功能性使得 Mellanox 網卡能夠滿足不同應用場景的需求,從常規的數據中心網絡…

win32匯編環境,對多行編輯框添加或刪除文本

;運行效果 ;win32匯編環境,對多行編輯框添加或刪除文本 ;主要要先設置文本的開始點與結束點&#xff0c;然后把一段文本頂替上去。沒有添加文本或刪除文本的概念&#xff0c;只有頂替。如果開始點與結束點都是前面文本的長度值&#xff0c;則成了從后面添加文本的效果。如果結束…

CSDN年度回顧:技術征途上的堅實步伐

嘿&#xff0c;時光過得可真快呀&#xff0c;就像那匹跑得飛快的白馬&#xff0c;嗖的一下&#xff0c;2024 年的日歷就這么悄無聲息地翻到了最后一頁。這會兒我回頭看看在 CSDN 上度過的這一年&#xff0c;心里那叫一個感慨萬千&#xff0c;滿滿的都是喜悅&#xff0c;就像心里…

泛型子類使用Builder提示:both methods have same erasure, yet neither hides the other

父類 Data Builder AllArgsConstructor NoArgsConstructor public class ParentClass {public String name; } 子類 AllArgsConstructor NoArgsConstructor Data SuperBuilder public class ChildClass<T> extends ParentClass {private T value; } 提示錯誤 builde…

Springboot集成Elasticsearch8.0(ES)版本,采用JAVA Client方式進行連接和實現CRUD操作

本文章介紹了 springboot t集成Elasticsearch8.0(ES)版本,如何通過 AVA Client方式進行連接和實現CRUD操作 在ES7.15版本之后,ES官方將高級客戶端 RestHighLevelClient標記為棄用狀態。同時推出了全新的 Java API客戶端 Elasticsearch Java API Client,該客戶端也將在 Ela…

人臉識別打卡系統--基于QT(附源碼)

逃離舒適區 項目源代碼放在我的倉庫中&#xff0c;有需要自取 項目地址 https://gitcode.com/hujiahangdewa/Face_recognition.git 文章目錄 一、項目結構分析二、服務器的搭建三、客戶端的搭建四、人臉識別庫的申請五、基于人臉識別庫的識別判斷六、QT人臉識別----調用百度ai…

人工智能在數字化轉型中的角色:從數據分析到智能決策

引言 在數字化轉型浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;正迅速崛起&#xff0c;成為推動企業創新和變革的關鍵力量。面對日益復雜的市場環境和激烈的行業競爭&#xff0c;企業亟需借助技術手段提高運營效率、優化決策過程&#xff0c;并增強市場競爭力。而AI…

react install

react 安裝 React 是一個用于構建用戶界面的 JavaScript 庫。以下是安裝 React 的步驟&#xff1a; 使用 Create React App Create React App 是一個官方支持的命令行工具&#xff0c;用于快速搭建 React 應用。 安裝 Node.js 和 npm 確保你的計算機上安裝了 Node.js 和 npm…

Android系統開發(二十):字體活起來,安卓自定義字體改造指南

為什么要寫這篇文章&#xff1f; 你是否厭倦了千篇一律的安卓默認字體&#xff1f;想讓你的設備從“乏味的配角”變成“炫酷的主角”&#xff1f;好消息&#xff01;從Android 12到Android 15&#xff0c;自定義字體變得更簡單、更強大。尤其是表情字體的更新&#xff0c;不僅…

django使用踩坑經歷

DRF 使用drf獲取序列化后的id visitor_serializer VisitorSaveSerializer(data{…}) if visitor_serializer.is_valid():visitor visitor_serializer.save() visitor_id visitor.pkpostgrepsql踩坑 django使用postgrepsql&#xff0c;使用聚合函數如:sum 等&#xff0c;被…

ASP.NET Core中 JWT 實現無感刷新Token

在 Web 應用開發中&#xff0c;用戶登錄狀態的管理至關重要。為了避免用戶頻繁遇到登錄過期的問題&#xff0c;我們可以通過實現 JWT&#xff08;JSON Web Token&#xff09;刷新機制來提升用戶體驗 推薦: 使用 Refresh Token&#xff08;雙 Token 機制&#xff09; 1. 生成和…

將 AzureBlob 的日志通過 Azure Event Hubs 發給 Elasticsearch(3.純python的實惠版)

前情&#xff1a; 將 AzureBlob 的日志通過 Azure Event Hubs 發給 Elasticsearch&#xff08;1.標準版&#xff09;-CSDN博客 將 AzureBlob 的日志通過 Azure Event Hubs 發給 Elasticsearch&#xff08;2.換掉付費的Event Hubs&#xff09;-CSDN博客 python腳本實現 厲害的…

python學opencv|讀取圖像(四十)掩模:三通道圖像的局部覆蓋

【1】引言 前序學習了使用numpy創建單通道的灰色圖像&#xff0c;并對灰色圖像的局部進行了顏色更改&#xff0c;相關鏈接為&#xff1a; python學opencv|讀取圖像&#xff08;九&#xff09;用numpy創建黑白相間灰度圖_numpy生成全黑圖片-CSDN博客 之后又學習了使用numpy創…

【全面解析】深入解析 TCP/IP 協議:網絡通信的基石

深入解析 TCP/IP 協議&#xff1a;網絡通信的基石 導語 你是否曾好奇&#xff0c;現代互聯網是如何實現全球設備之間的高速、穩定和可靠通信的&#xff1f;無論是瀏覽網頁、發送電子郵件&#xff0c;還是進行視頻通話&#xff0c;背后都離不開 TCP/IP 協議 的支撐。作為互聯網…

全面解析 Java 流程控制語句

Java學習資料 Java學習資料 Java學習資料 在 Java 編程中&#xff0c;流程控制語句是構建程序邏輯的關鍵部分&#xff0c;它決定了程序的執行順序和走向。通過合理運用這些語句&#xff0c;開發者能夠實現各種復雜的業務邏輯&#xff0c;讓程序更加靈活和智能。 順序結構 順…

Linux系統常用指令

查找文件 find / -name "<文件名>" 2>/dev/null //遍歷系統查找指定文件名文件ls -l | grep "<文件名>" //列出當前目錄下有關文件名的文件find -name sw_sfp_alarm_cfg.xml //查找文件名對應路徑 切換目錄 編輯文件 vi <文件…

【Unity】ScrollViewContent適配問題(Contentsizefilter不刷新、ContentSizeFilter失效問題)

最近做了一個項目&#xff0c;菜單欄讀取數據后自動生成&#xff0c;結果用到了雙重布局 父物體 嘗試了很多方式&#xff0c;也看過很多大佬的文章&#xff0c;后來自己琢磨了一下&#xff0c;當子物體組件自動生成之后&#xff0c;使用以下以下代碼效果會好一些&#xff1a; …

AI輔助醫學統計分析APP

AI輔助醫學統計分析APP 醫學統計分析的困難點在于開始階段分析的規劃和得出分析結果之后分析結果的解釋&#xff0c;前者之所以困難是因為分析方法繁多又有不同的使用條件&#xff0c;后者則是因為結果中術語較多&#xff0c;且各種分析方法術語又有不同&#xff0c;非統計專業…

[STM32 HAL庫]串口中斷編程思路

一、前言 最近在準備藍橋杯比賽&#xff08;嵌入式賽道&#xff09;&#xff0c;研究了以下串口空閑中斷DMA接收不定長的數據&#xff0c;感覺這個方法的接收效率很高&#xff0c;十分好用。方法配置都成功了&#xff0c;但是有一個點需要進行考慮&#xff0c;就是一般我們需要…

淺談Java之AJAX

一、基本介紹 在Java開發中&#xff0c;AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一種用于創建動態網頁的技術&#xff0c;它允許網頁在不重新加載整個頁面的情況下與服務器進行交互。 二、關鍵點和示例 1. AJAX的基本原理 AJAX通過JavaScript的XMLHtt…