Arthas tt(方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)
- 2025-04-19 黑龙江
本文字数:12362 字
阅读完需:约 41 分钟

@[toc]
二、命令列表
2.3 monitor/watch/trace/stack/tt 相关
2.3.4 tt(方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)
使用场景
:
watch
虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。
提示
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
注意事项
:
tt 命令的实现是:把函数的入参/返回值等,保存到一个
Map<Integer, TimeFragment>
里,默认的大小是 100。tt 相关功能在使用完之后,需要手动释放内存,否则长时间可能导致 OOM。退出 arthas 不会自动清除 tt 的缓存 map。
命令参数解析 -t:tt 命令有很多个主参数,
-t
就是其中之一。这个参数的表明希望记录下类*Test
的print
方法的每次执行情况。命令参数解析 -n 3:当你执行一个调用量不高的方法时可能你还能有足够的时间用
CTRL+C
中断 tt 命令记录的过程,但如果遇到调用量非常大的方法,瞬间就能将你的 JVM 内存撑爆。此时你可以通过-n
参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断 tt 命令的记录过程,避免人工操作无法停止的情况。命令参数解析 -m 1:通过
-m
参数指定 Class 匹配的最大数量,防止匹配到的 Class 数量太多导致 JVM 挂起,默认值是 50。
参数说明:
监控的维度说明:
举例 1:记录调用
基础语法
:tt -t 全路径类名 方法名
[arthas@7265]$ tt -t com.hero.lte.ems.security.service.impl.LdapService login
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 224 ms, listenerId: 6
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1000 2024-09-19 13:40:59 174.854817 true false 0x45b76c27 LdapService login
1001 2024-09-19 13:41:11 7.661214 true false 0x45b76c27 LdapService login
[arthas@7265]$
举例 2:显示所有已经记录的列表
基础语法
:tt -l
[arthas@7265]$ tt -l
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1000 2024-09-19 13:40:59 174.854817 true false 0x45b76c27 LdapService login
1001 2024-09-19 13:41:11 7.661214 true false 0x45b76c27 LdapService login
Affect(row-cnt:2) cost in 1 ms.
[arthas@7265]$
举例 3:查看某条记录详细信息
基础语法
:tt -i INDEX
[arthas@7265]$ tt -i 1001
INDEX 1001
GMT-CREATE 2024-09-19 13:41:11
COST(ms) 7.661214
OBJECT 0x45b76c27
CLASS com.hero.lte.ems.security.service.impl.LdapService
METHOD login
IS-RETURN true
IS-EXCEPTION false
PARAMETERS[0] @LdapLoginRequest[
username=@String[testuser2],
password=@String[Hero@1993],
principal=@String[testuser2@MS-DCS.BEE.VIMPELCOM.RU],
keytabFilePath=null,
ldapFlag=null,
domainName=@String[ms-dcs.bee.vimpelcom.ru],
baseDn=@String[dc=ms-dcs,dc=bee,dc=vimpelcom,dc=ru],
adminBindDn=@String[cn=Tech_Hytera_MS,ou=TechDir_Msk,ou=Moscow,dc=ms-dcs,dc=bee,dc=vimpelcom,dc=ru],
adminBindPassword=@String[Bingo@1993],
userSearchDn=@String[],
userSearchScope=@Integer[2],
userIdAttribute=@String[sAMAccountName],
groupSearchDn=@String[DC=ms-dcs,DC=bee,DC=vimpelcom,DC=ru],
groupSearchScope=@Integer[2],
groupFilter=@String[(objectClass=*)],
groupMemberAttribute=@String[member],
createTime=@Date[2024-09-17 16:20:38,000],
updateTime=@Date[2024-09-17 16:20:38,000],
ldapConnectionSecurityMode=@Integer[0],
port=@Integer[636],
ignoreReferrals=@Integer[0],
enableFullDnForGroupMemberAttribute=@Integer[0],
validGroup=@String[testou1,APP_Hytera_MS],
searchGroupFilter=@String[(&(objectClass=*)(member=*))],
]
RETURN-OBJ @ResultSet[
errorCode=@String[43],
errorString=@String[kerberos authentication failed.],
errorParams=null,
resultVal=null,
]
Affect(row-cnt:1) cost in 34 ms.
[arthas@7265]$
举例 4:tt 对重载的支持
不知道大家是否有在使用过程中遇到以下困惑
Arthas 似乎很难区分出重载的方法我只需要观察特定参数,但是 tt 却全部都给我记录了下来条件表达式也是用 OGNL 来编写,核心的判断对象依然是 Advice 对象。除了 tt 命令之外,watch、trace、stack 命令也都支持条件表达式。
解决方法重载:
# 指定入参的长度=1
tt -t *Test print params.length==1`
# 指定入参的类型
tt -t *Test print 'params[1] instanceof Integer
# 指定固定的入参值
tt -t *Test print params[0].mobile=="13989838402
举例 5:重做一次调用
当你稍稍做了一些调整之后,你可能需要前端系统重新触发一次你的调用,此时得求爷爷告奶奶的需要前端配合联调的同学再次发起一次调用。而有些场景下,这个调用不是这么好触发的。
tt
命令由于保存了当时调用的所有现场信息,所以我们可以自己主动对一个 INDEX
编号的时间片自主发起一次调用,从而解放你的沟通成本。此时你需要 -p
参数。通过 --replay-times
指定 调用次数,通过 --replay-interval
指定多次调用间隔(单位 ms, 默认 1000ms)
基础语法
:tt -i INDEX -p
[arthas@7265]$ tt -i 1001 -p
RE-INDEX 1001
GMT-REPLAY 2024-09-19 14:00:54
OBJECT 0x45b76c27
CLASS com.hero.lte.ems.security.service.impl.LdapService
METHOD login
PARAMETERS[0] @LdapLoginRequest[
username=@String[testuser2],
password=@String[Hero@1993],
principal=@String[testuser2@MS-DCS.BEE.VIMPELCOM.RU],
keytabFilePath=null,
ldapFlag=null,
domainName=@String[ms-dcs.bee.vimpelcom.ru],
baseDn=@String[dc=ms-dcs,dc=bee,dc=vimpelcom,dc=ru],
adminBindDn=@String[cn=Tech_Hytera_MS,ou=TechDir_Msk,ou=Moscow,dc=ms-dcs,dc=bee,dc=vimpelcom,dc=ru],
adminBindPassword=@String[Bingo@1993],
userSearchDn=@String[],
userSearchScope=@Integer[2],
userIdAttribute=@String[sAMAccountName],
groupSearchDn=@String[DC=ms-dcs,DC=bee,DC=vimpelcom,DC=ru],
groupSearchScope=@Integer[2],
groupFilter=@String[(objectClass=*)],
groupMemberAttribute=@String[member],
createTime=@Date[2024-09-17 16:20:38,000],
updateTime=@Date[2024-09-17 16:20:38,000],
ldapConnectionSecurityMode=@Integer[0],
port=@Integer[636],
ignoreReferrals=@Integer[0],
enableFullDnForGroupMemberAttribute=@Integer[0],
validGroup=@String[testou1,APP_Hytera_MS],
searchGroupFilter=@String[(&(objectClass=*)(member=*))],
]
IS-RETURN true
IS-EXCEPTION false
COST(ms) 39.397075
RETURN-OBJ @ResultSet[
errorCode=@String[43],
errorString=@String[kerberos authentication failed.],
errorParams=null,
resultVal=null,
]
Time fragment[1001] successfully replayed 1 times.
[arthas@7265]$
你会发现结果虽然一样,但调用的路径发生了变化,由原来的程序发起变成了 Arthas 自己的内部线程发起的调用了。
本人其他相关文章链接
1.Arthas 全攻略:让调试变得简单2.Arthas dashboard(当前系统的实时数据面板)3.Arthas thread(查看当前JVM的线程堆栈信息)4.Arthas jvm(查看当前JVM的信息)5.Arthas sysprop(查看和修改JVM的系统属性)6.Arthas sysenv(查看JVM的环境变量)7.Arthas vmoption(查看和修改 JVM里诊断相关的option)8.Arthas getstatic(查看类的静态属性 )9.Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)10.Arthas logger(查看 logger 信息,更新 logger level)11.Arthas mbean(查看 Mbean 的信息)12.Arthas memory(查看 JVM 内存信息)13.Arthas ognl(执行ognl表达式)14.Arthas perfcounter(查看当前 JVM 的 Perf Counter 信息)15.Arthas vmtool(从 jvm 里查询对象,执行 forceGc)16.Arthas jad(字节码文件反编译成源代码 )17.Arthas mc(Memory Compiler/内存编译器 )18.Arthas redefine(加载外部的.class文件,redefine到JVM里 )19.Arthas classloader (查看 classloader 的继承树,urls,类加载信息)20.Arthas sc(查看JVM已加载的类信息 )21.Arthas sm(查看已加载类的方法信息 )22.Arthas monitor(方法执行监控)23.Arthas stack (输出当前方法被调用的调用路径)24.Arthas trace (方法内部调用路径,并输出方法路径上的每个节点上耗时)25.Arthas tt(方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)26.Arthas watch (方法执行数据观测)27.Arthas profiler(使用async-profiler对应用采样,生成火焰图)
版权声明: 本文为 InfoQ 作者【刘大猫】的原创文章。
原文链接:【http://xie.infoq.cn/article/fef87f7aba179c5f596e20147】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。

刘大猫
还未添加个人签名 2022-08-23 加入
还未添加个人简介
评论