arthas使用总结
引言
这里记录一下我在使用 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 使用总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)