arthas 简要指令说明
arthas
一款alibaba开源的java 在线分析工具,一般用于分析生产环境的各种故障,或者分析各种性能指标。
下载运行
curl -O https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar
curl https://arthas.aliyun.com/arthas-boot.jar --output arthas.jar && java -jar arthas.jar
查看整体情况
包括内存,jvm,gc,线程等内容
dashboard
查看线程情况
命令 | 作用 |
---|---|
thread | 查看最近20个线程 |
thread |
查看某个线程的堆栈 |
thread --all | 打印全部线程信息 |
thread -n 3 | 查看cpu使用率 top 3 线程 |
thread -b | 查看阻塞线程 |
thread -n 3 -i 5000 | 查看5s内 cpu top3 线程 |
执行Spring 命令
用于获取一个bean,调用某个方法,获取某个bean的成员变量的值,修改bean成员变量的值等等
方案1
1.先获取applicationContext对象 执行如下代码后,随意走一个接口
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
2.获取context对象后 ,直接getBean
获取任意Bean对象,然后执行操作
tt -i 1000 -w 'target.getApplicationContext().getBean("dataSource").dataSourceMap.clear()'
方案2
vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'
反编译查看源码
查看线上实际运行的代码
jad package_name.class_name
watch监控方法调用情况
查看指定方法每次调用的输入输出参数,抛出的异常信息
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 函数名表达式匹配 |
express | 观察表达式,默认值:{params, target, returnObj} |
condition-express | 条件表达式 |
[b] | 在函数调用之前观察 |
[e] | 在函数异常之后观察 |
[s] | 在函数返回之后观察 |
[f] | 在函数结束之后(正常返回和异常返回)观察 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[x:] | 指定输出结果的属性遍历深度,默认为 1,最大值是 4 |
[m |
指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch |
watch 参数规则 | watch 包名 方法名 '{查询对象}' '条件' 选项 |
---|---|
查看第一个入参(List)的第一个元素 且只监控一次 | watch Test test params[0].get(0) -n 1 |
参数过滤 | watch Test test "params[0].{? #this.age > 5}.{name}" -n 1 |
复杂操作 | watch Test test '(#test=params[0].{name}, #test.add("abc"), #test)' -n 1 |
声明变量 | watch Test test '(#test=new java.util.ArrayList(), #test.add("abc"), #test)' -n |
数组塞选 | watch Test test '@Test@n.entrySet().iterator.{? #this.key.name() == "RUN"}' -n 1 |
静态变量 | watch Test test '@a.b@c' -n 1 |
Map中的值 | watch Test test '@Test@n.keys' -n 1 |
打印异常 -e 表示异常事打印 -x表示打印对象的层级 | watch cn.bobmao.pro.runtime.common.util.JavaMailUtil sendEmail "throwExp" -e -x 2 |
查询对象 | 说明 |
---|---|
loader | 本次调用类所在的 ClassLoader |
clazz | 本次调用类的 Class 引用 |
method | 本次调用方法反射引用 |
target | 本次调用类的实例 |
params | 本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组 |
returnObj | 本次调用返回的对象。 |
throwExp | 本次调用抛出的异常 |
查询静态变量 getstatic
getstatic 命令可以方便的查看类的静态属性
# 直接查看静态变量的值
getstatic class_name field_name
# 直接操作静态变量
getstatic com.alibaba.arthas.Test m 'entrySet().iterator.{? #this.key=="a"}'
指定classloader
有时候需要指定classloader才能访问类,因为这个类不是用默认的classloader加载的或者存在多个classloader。此时需要你先获取classloader
然后在getstatic中使用-c参数传入 classloader的hash值
getstatic -c classLoaderHash demo.MathGame random
查看进程内的所有classloader和层次关系
classloader -t
spring的classloader
org.springframework.boot.loader.LaunchedURLClassLoader
获取spring classloader的hashcode (随便找一个spring bean的类)
classloader -l cn.bobmao.pro.application.controller.ApplicationController
dumpheap
说明 | 操作 |
---|---|
dump到指定目录 | heapdump /tmp/dump.hprof |
只 dump live 对象 | heapdump --live /tmp/dump.hprof |
查看jvm统计
查看java进程的启动事件,jdk版本,加载的jar包,已加载类的数量等信息
jvm
参数名 | 参数说明 |
---|---|
COUNT | JVM 当前活跃的线程数 |
DAEMON-COUNT | JVM 当前活跃的守护线程数 |
PEAK-COUNT | 从 JVM 启动开始曾经活着的最大线程数 |
STARTED-COUNT | 从 JVM 启动开始总共启动过的线程次数 |
DEADLOCK-COUNT | JVM 当前死锁的线程数 |
MAX-FILE-DESCRIPTOR-COUNT | JVM 进程最大可以打开的文件描述符数 |
OPEN-FILE-DESCRIPTOR-COUNT | JVM 当前打开的文件描述符数 |
Logger
查看logger日志和修改level等级,比如生产的日志写了一句log.debug 但默认日志等级是info,导致相关日志没有打印,使用本命令可以不重启即可修改等级。
命令 | 作用 |
---|---|
logger | 查看当前logger配置 |
logger -n logger_name | 查看具体logger的配置 |
logger --name ROOT --level debug | 修改日志等级 ROOT是logger的name |
ognl表达式
阿尔萨斯的很多命令的参数都是支持ognl表达式,比如watch的打印内容 getstatic的执行命令
它允许直接执行指定的java代码,当然ognl本身也是个命令,允许用户单独执行
- OGNL 特殊用法请参考:https://github.com/alibaba/arthas/issues/71在新窗口打开
- OGNL 表达式官方指南:https://commons.apache.org/proper/commons-ognl/language-guide.html
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/opt/java/8.0.181-zulu/jre],
@String[OpenJDK Runtime Environment],
]
$ classloader -t
+-BootstrapClassLoader
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@301ec38b
+-com.taobao.arthas.agent.ArthasClassloader@472067c7
+-jdk.internal.loader.ClassLoaders$AppClassLoader@4b85612c
+-org.springframework.boot.loader.LaunchedURLClassLoader@7f9a81e8
$ ognl -c 7f9a81e8 @org.springframework.boot.SpringApplication@logger
@Slf4jLocationAwareLog[
FQCN=@String[org.apache.commons.logging.LogAdapter$Slf4jLocationAwareLog],
name=@String[org.springframework.boot.SpringApplication],
logger=@Logger[Logger[org.springframework.boot.SpringApplication]],
]
$
退出调试
操作 | 命令 |
---|---|
关闭本次连结 | quit exit |
关闭调试 | stop |
reset
还原所有的增强类 清除所有更改
trace
打印方法内部调用路径,并输出方法路径上的每个节点上耗时
用于分析接口调用慢,方法是否被调用了等情况。
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n:] | 命令执行次数 |
#cost | 方法执行耗时 |
$ trace demo.MathGame run '#cost > 10'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 41 ms.
`---ts=2018-12-04 01:12:02;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
`---[12.033735ms] demo.MathGame:run()
+---[0.006783ms] java.util.Random:nextInt()
+---[11.852594ms] demo.MathGame:primeFactors()
`---[0.05447ms] demo.MathGame:print()
stack
当方法被执行时,输出当前方法被调用的调用路径
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n:] | 执行次数限制 |
[m |
指定 Class 最大匹配数量,默认值为 50。 实际指class分析层数 |
stack demo.MathGame primeFactors -m 2
stack demo.MathGame primeFactors 'params[0]<0' -n 2
stack demo.MathGame primeFactors '#cost>5'
$ stack demo.MathGame primeFactors -m 1
Press Q or Ctrl+C to abort.
Affect(class count:1 , method count:1) cost in 561 ms, listenerId: 5.
ts=2022-12-25 21:07:07;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@b4aac2
@demo.MathGame.primeFactors()
at demo.MathGame.run(MathGame.java:46)
at demo.MathGame.main(MathGame.java:38)
vmtool
vmtool 利用JVMTI接口,实现查询内存对象,强制 GC 等功能。
获取对象实例信息
$ vmtool --action getInstances --className java.lang.String --limit 10
@String[][
@String[com/taobao/arthas/core/shell/session/Session],
@String[com.taobao.arthas.core.shell.session.Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/],
@String[java/util/concurrent/ConcurrentHashMap$ValueIterator],
@String[java/util/concurrent/locks/LockSupport],
]
指定 classloader hash
vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext
通过vmtool拿到 applicationContext对象
vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'
强制 GC
vmtool --action forceGc
interrupt 指定线程(设置该线程的中断标志为true)
vmtool --action interruptThread -t 1
profiler火焰图
Only support Linux/Mac.
profiler 命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。
参数名称 | 参数说明 |
---|---|
action | 要执行的操作 |
actionArg | 属性名模式 |
[i:] | 采样间隔(单位:ns)(默认值:10'000'000,即 10 ms) |
[f:] | 将输出转储到指定路径 |
[d:] | 运行评测指定秒 |
[e:] | 要跟踪哪个事件(cpu, alloc, lock, cache-misses 等),默认是 cpu |
启动
$ profiler start
Started [cpu] profiling
获取采样树
$ profiler getSamples
23
查看状态
$ profiler status
[cpu] profiling is running for 4 seconds
停止并生成文档
$ profiler stop --format html
profiler output file: /tmp/test/arthas-output/20211207-111550.html
OK
用户案例
https://github.com/alibaba/arthas/issues?q=label%3Auser-case