文章目录
- 二、命令列表
- 2.3 monitor/watch/trace/stack/tt 相关
- 2.3.4 tt(方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)
- 举例1:记录调用
- 举例2:显示所有已经记录的列表
- 举例3:查看某条记录详细信息
- 举例4:tt对重载的支持
- 举例5:重做一次调用
- 本人其他相关文章链接
二、命令列表
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。
参数说明:
tt的参数 | 说明 |
---|---|
-t | 记录某个方法在一个时间段中的调用 |
-l | 显示所有已经记录的列表 |
-n 次数 | 只记录多少次 |
-s 表达式 | 搜索表达式 |
-i 索引号 | 查看指定索引号的详细调用信息 |
-p | 重新调用:指定的索引号时间碎片 |
监控的维度说明:
表格字段 | 字段解释 |
---|---|
INDEX | 时间片段记录编号,每一个编号代表着一次调用,后续 tt 还有很多命令都是基于此编号指定记录操作,非常重要。 |
TIMESTAMP | 方法执行的本机时间,记录了这个时间片段所发生的本机时间 |
COST(ms) | 方法执行的耗时 |
IS-RET | 方法是否以正常返回的形式结束 |
IS-EXP | 方法是否以抛异常的形式结束 |
OBJECT | 执行对象的hashCode() ,注意,曾经有人误认为是对象在 JVM 中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体 |
CLASS | 执行的类名 |
METHOD | 执行的方法名 |
举例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对应用采样,生成火焰图)