Arthas(阿尔萨斯) — 阿里在线诊断神器
Arthas简介
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。
Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
Github: https://github.com/alibaba/arthas
文档: https://arthas.aliyun.com/doc/
参考:https://alibaba.github.io/arthas/quick-start.html
演示:https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn
命令列表: https://arthas.aliyun.com/doc/commands.html
测试应用
首先,我们随便来一个测试项目,代码如下:
package cn.appblog.arthas;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yezhou
* @version 1.0
* @date 2020/8/20 10:28
*/
@RestController
public class TestController {
@GetMapping(value = "test")
public User abc(Integer integer) {
if (integer == 0) {
throw new IllegalArgumentException("参数 0 异常");
}
User user = new User();
user.setName("Joe.Ye");
user.setAge(integer);
return user;
}
}
Arthas服务启动及使用
(1)启动服务
E:\Java-Project\arthas>java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.3.9
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 11908
[2]: 26932 cn.appblog.arthas.ArthasApplication
2 //选择应用进程
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.3.9?mirror=aliyun
[INFO] File size: 11.44 MB, downloaded size: 11.20 MB, downloading ...
[INFO] Download arthas success.
[INFO] arthas home: C:\Users\yezhou\.arthas\lib\3.3.9\arthas
[INFO] Try to attach process 11908
Exception in thread "main" java.lang.IllegalArgumentException: Can not find tools.jar under java home: C:\Program Files\Java\jre1.8.0_231, please try to start arthas-boot with full path java. Such as /opt/jdk/bin/java -jar arthas-boot.jar
at com.taobao.arthas.boot.ProcessUtils.findJavaHome(ProcessUtils.java:222)
at com.taobao.arthas.boot.ProcessUtils.startArthasCore(ProcessUtils.java:233)
at com.taobao.arthas.boot.Bootstrap.main(Bootstrap.java:506)
(2)若报如上错误,则以如下方式启动
set JAVA_HOME="C:\Program Files\Java\jdk1.8.0_231\jre"
"C:\Program Files\Java\jdk1.8.0_231\bin\java.exe" -jar arthas-boot.jar
(3)停止服务
java -jar C:\Users\yezhou\.arthas\lib\3.3.9\arthas\arthas-client.jar 127.0.0.1 3658 -c "stop"
(4)命令列表
[arthas@26932]$ help
NAME DESCRIPTION
help Display Arthas Help
keymap Display all the available keymap for the specified connection.
sc Search all the classes loaded by JVM
sm Search the method of classes loaded by JVM
classloader Show classloader info
jad Decompile class
getstatic Show the static field of a class
monitor Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
stack Display the stack trace for the specified class and method
thread Display thread info, thread stack
trace Trace the execution time of specified method invocation.
watch Display the input/output parameter, return object, and thrown exception of specified method invocation
tt Time Tunnel
jvm Display the target JVM information
perfcounter Display the perf counter infornation.
ognl Execute ognl expression.
mc Memory compiler, compiles java files into bytecode and class files in memory.
redefine Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)
dashboard Overview of target jvm's thread, memory, gc, vm, tomcat info.
dump Dump class byte array from JVM
heapdump Heap dump
options View and change various Arthas options
cls Clear the screen
reset Reset all the enhanced classes
version Display Arthas version
session Display current session information
sysprop Display, and change the system properties.
sysenv Display the system env.
vmoption Display, and update the vm diagnostic options.
logger Print logger info, and update the logger level
history Display command history
cat Concatenate and print files
echo write arguments to the standard output
pwd Return working directory name
mbean Display the mbean information
grep grep command for pipes.
tee tee command for pipes.
profiler Async Profiler. https://github.com/jvm-profiling-tools/async-profiler
stop Stop/Shutdown Arthas server and exit the console.
Arthas命令
sc 命令
命令介绍:该命令是Search-Class
英文的缩写,用于查看JVM已加载的类信息
常用参数详情
-d
: 参数用于输出详细的类相关信息(类全限定名,存放路径,接口,注解,继承父类,类加载器等),支持模糊查询-f
: 参数需要配合 -d 命令一起使用, 在上述类信息中加入字段信息,包括权限、类型、名字
例子(使用模糊的方式):
sc -d -f *TestController
[arthas@26932]$ sc -d -f *TestController
class-info cn.appblog.arthas.TestController
code-source /E:/Java-Project/arthas/target/classes/
name cn.appblog.arthas.TestController
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name TestController
modifier public
annotation org.springframework.web.bind.annotation.RestController
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@64b8f8f4
classLoaderHash 18b4aac2
fields
Affect(row-cnt:1) cost in 18 ms.
其他参数:
-E
: 开启正则表达式匹配,默认为通配符匹配-c
: 类名表达式匹配
sm 命令
命令介绍:该命令是Search-Method
英文的缩写,用于查看已加载类的方法信息
常用参数
-d
: 方法详情
例子:(模糊匹配找到TestController
下的abc
方法详情)
sm -d *TestController abc
[arthas@26932]$ sm -d *TestController abc
declaring-class cn.appblog.arthas.TestController
method-name abc
modifier public
annotation org.springframework.web.bind.annotation.GetMapping
parameters java.lang.Integer
return cn.appblog.arthas.User
exceptions
classLoaderHash 18b4aac2
Affect(row-cnt:1) cost in 17 ms.
非常用参数:
-E
: 开启正则表达式匹配,默认为通配符匹配-c
: 类名表达式匹配
jad 命令
命令介绍:该命令可以反编译出已加载类的源代码,如果没有线下环境,我们可以在线上查看到底哪行代码出问题。
例子:
jad *TestController
[arthas@26932]$ jad *TestController
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@64b8f8f4
Location:
/E:/Java-Project/arthas/target/classes/
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* cn.appblog.arthas.User
*/
package cn.appblog.arthas;
import cn.appblog.arthas.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping(value={"test"})
public User abc(Integer integer) {
if (integer == 0) {
throw new IllegalArgumentException("鍙傛暟 0 寮傚父");
}
User user = new User();
user.setName("Joe.Ye");
user.setAge(integer);
return user;
}
}
Affect(row-cnt:1) cost in 860 ms.
tt 命令
tt 命令有点强,使用该命令,会有一个记录表,请求来时,会将请求记录下来,可以进行重放(由 Arthas 启动线程请求)
常用参数:
-t
: 开启方法监听,记录下TestController
中方法abc
的调用情况
tt -t *TestController abc
[arthas@26932]$ tt -t *TestController abc
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 110 ms, listenerId: 1
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-----------------------------------------------------------------------------------------------------------------------
1000 2020-08-20 15:44:32 0.675401 true false 0x3d4f4fbf TestController abc
1001 2020-08-20 15:44:45 0.2588 false true 0x3d4f4fbf TestController abc
1002 2020-08-20 15:45:03 0.049399 true false 0x3d4f4fbf TestController abc
接下来我们按 Q 或者 Ctrl+C 退出监听。
-i
:i
是指index
索引的意思,可以用来找出之前请求的信息
tt -i 1000
[arthas@26932]$ tt -i 1000
INDEX 1000
GMT-CREATE 2020-08-20 15:44:32
COST(ms) 0.675401
OBJECT 0x3d4f4fbf
CLASS cn.appblog.arthas.TestController
METHOD abc
IS-RETURN true
IS-EXCEPTION false
PARAMETERS[0] @Integer[20]
RETURN-OBJ @User[
name=@String[Joe.Ye],
age=@Integer[20],
]
Affect(row-cnt:1) cost in 9 ms.
[arthas@26932]$ tt -i 1001
INDEX 1001
GMT-CREATE 2020-08-20 15:44:45
COST(ms) 0.2588
OBJECT 0x3d4f4fbf
CLASS cn.appblog.arthas.TestController
METHOD abc
IS-RETURN false
IS-EXCEPTION true
PARAMETERS[0] null
THROW-EXCEPTION java.lang.NullPointerException
at cn.appblog.arthas.TestController.abc(TestController.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Affect(row-cnt:1) cost in 12 ms.
-l
: 找出列表所有请求
tt -l
[arthas@26932]$ tt -l
INDEX TIMESTAMP COST(ms IS-RE IS-EXP OBJECT CLASS METHOD
) T
-----------------------------------------------------------------------------------------------------------------------
1000 2020-08-20 15:44:32 0.675401 true false 0x3d4f4fbf TestController abc
1001 2020-08-20 15:44:45 0.2588 false true 0x3d4f4fbf TestController abc
1002 2020-08-20 15:45:03 0.049398 true false 0x3d4f4fbf TestController abc
Affect(row-cnt:3) cost in 3 ms.
-p
: 该之类用于重做一次调用,一般来说,前端调起请求后。结果之前没看到,再次在前端调起太麻烦,那么可以使用该参数
tt -i 1000 -p
上述1000
是指索引,重新请求类似于-i
输出消息
[arthas@26932]$ tt -i 1000 -p
RE-INDEX 1000
GMT-REPLAY 2020-08-20 16:03:18
OBJECT 0x3d4f4fbf
CLASS cn.appblog.arthas.TestController
METHOD abc
PARAMETERS[0] @Integer[20]
IS-RETURN true
IS-EXCEPTION false
COST(ms) 0.200501
RETURN-OBJ @User[
name=@String[Joe.Ye],
age=@Integer[20],
]
Time fragment[1000] successfully replayed 1 times.
-n
: 指定抓取次数,达到次数后自动停止
tt -t *TestController abc -n 3
[arthas@26932]$ tt -t *TestController abc -n 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms, listenerId: 2
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-----------------------------------------------------------------------------------------------------------------------
1003 2020-08-20 16:05:48 0.0771 true false 0x3d4f4fbf TestController abc
1004 2020-08-20 16:05:48 0.0307 true false 0x3d4f4fbf TestController abc
1005 2020-08-20 16:05:49 0.026501 true false 0x3d4f4fbf TestController abc
Command execution times exceed limit: 3, so command will exit. You can set it with -n option.
-w
: 用作输出信息,可以找出请求过的信息,参数、以及是否抛出异常
找出正常返回对象、已经请求参数值
tt -i 1000 -w '{params[0], target, returnObj}'
[arthas@26932]$ tt -i 1000 -w '{params[0], target, returnObj}'
@ArrayList[
@Integer[20],
@TestController[cn.appblog.arthas.TestController@3d4f4fbf],
@User[User(name=Joe.Ye, age=20)],
]
Affect(row-cnt:1) cost in 52 ms.
出现异常的线程,找出相关异常信息
tt -i 1001 -w '{params[0], target,throwExp}'
[arthas@26932]$ tt -i 1001 -w '{params[0], target,throwExp}'
@ArrayList[
null,
@TestController[cn.appblog.arthas.TestController@3d4f4fbf],
@NullPointerException[java.lang.NullPointerException],
]
Affect(row-cnt:1) cost in 1 ms.
如果我们发现异常,想看看什么异常,怎么办呢?
tt -i 1001 -w throwExp
[arthas@26932]$ tt -i 1001 -w throwExp
java.lang.NullPointerException
at cn.appblog.arthas.TestController.abc(TestController.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Affect(row-cnt:1) cost in 1 ms.
dashboard
当前系统的实时数据面板,可以显示 JVM 内存使用情况,Java 版本信息
[arthas@26932]$ dashboard
ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPT DAEMON
5 Attach Listener system 5 RUNNABLE 0 0:0 false true
20 Catalina-utility-1 main 1 WAITING 0 0:0 false false
21 Catalina-utility-2 main 1 TIMED_WAI 0 0:0 false false
38 DestroyJavaVM main 5 RUNNABLE 0 0:3 false false
3 Finalizer system 8 WAITING 0 0:0 false true
6 Monitor Ctrl-Break main 5 RUNNABLE 0 0:0 false true
16 RMI Scheduler(0) system 5 WAITING 0 0:0 false true
12 RMI TCP Accept-0 system 5 RUNNABLE 0 0:0 false true
2 Reference Handler system 10 WAITING 0 0:0 false true
4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true
54 Timer-for-arthas-dashboard-49 system 5 RUNNABLE 0 0:0 false true
46 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0 0:0 false true
52 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0 0:0 false true
Memory used total max usage GC
heap 100M 247M 3614M 2.79% gc.ps_scavenge.count 5
ps_eden_space 62M 64M 1325M 4.69% gc.ps_scavenge.time(ms) 105
ps_survivor_space 10M 10M 10M 99.87% gc.ps_marksweep.count 2
ps_old_gen 28M 172M 2711M 1.03% gc.ps_marksweep.time(ms) 194
nonheap 50M 56M -1 89.09%
code_cache 3M 7M 240M 1.55%
Runtime
os.name Windows 10
os.version 10.0
java.version 1.8.0_231
java.home C:\Program Files\Java\jdk1.8.0_231\jre
systemload.average -1.00
processors 4
uptime 3527s
thread
常见参数
-i
: 指定时间内采集
thread -i 2000
效果和thread
类似,但是是一段时间数据
[arthas@26932]$ thread -i 2000
Threads Total: 32, NEW: 0, RUNNABLE: 12, BLOCKED: 0, WAITING: 16, TIMED_WAITING: 4, TERMINATED: 0
ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPT DAEMON
5 Attach Listener system 5 RUNNABLE 0 0:0 false true
20 Catalina-utility-1 main 1 WAITING 0 0:0 false false
21 Catalina-utility-2 main 1 TIMED_WAI 0 0:0 false false
38 DestroyJavaVM main 5 RUNNABLE 0 0:3 false false
3 Finalizer system 8 WAITING 0 0:0 false true
6 Monitor Ctrl-Break main 5 RUNNABLE 0 0:0 false true
16 RMI Scheduler(0) system 5 WAITING 0 0:0 false true
12 RMI TCP Accept-0 system 5 RUNNABLE 0 0:0 false true
2 Reference Handler system 10 WAITING 0 0:0 false true
4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true
46 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0 0:0 false true
52 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0 0:0 false true
47 arthas-NettyWebsocketTtyBoots system 5 RUNNABLE 0 0:0 false true
50 arthas-UserStat system 5 WAITING 0 0:0 false true
53 arthas-command-execute system 5 RUNNABLE 0 0:1 false true
48 arthas-shell-server system 5 TIMED_WAI 0 0:0 false true
49 arthas-shell-server system 5 TIMED_WAI 0 0:0 false true
45 arthas-timer system 5 WAITING 0 0:0 false true
22 container-0 main 5 TIMED_WAI 0 0:0 false false
36 http-nio-8080-Acceptor main 5 RUNNABLE 0 0:0 false true
24 http-nio-8080-BlockPoller main 5 RUNNABLE 0 0:0 false true
35 http-nio-8080-ClientPoller main 5 RUNNABLE 0 0:0 false true
25 http-nio-8080-exec-1 main 5 WAITING 0 0:0 false true
34 http-nio-8080-exec-10 main 5 WAITING 0 0:0 false true
26 http-nio-8080-exec-2 main 5 WAITING 0 0:0 false true
27 http-nio-8080-exec-3 main 5 WAITING 0 0:0 false true
28 http-nio-8080-exec-4 main 5 WAITING 0 0:0 false true
-n
: 找出 cpu 使用率最高的几个线程
thread -n 3
[arthas@26932]$ thread -n 3
"Reference Handler" Id=2 cpuUsage=0% WAITING on java.lang.ref.Reference$Lock@94829b
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@94829b
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"Finalizer" Id=3 cpuUsage=0% WAITING on java.lang.ref.ReferenceQueue$Lock@63956277
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.ReferenceQueue$Lock@63956277
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
"Signal Dispatcher" Id=4 cpuUsage=0% RUNNABLE
-b
找到持有锁的线程,有时候请求后,一直卡住,那么可以使用该方式去查找持有锁的线程。注意该方式不支持显示锁也就是lock
接口的
thread -b
[arthas@26932]$ thread -b
No most blocking thread found!
jvm
输出 jvm 相关信息,包括加载类的路径,启动类路径,加载类个数等等
trace 命令
该命令有点强,用于查看接口调用时间,可以找出接口在调用不同方法时所花费的时间,可以用作性能调优。
常用参数:
-n
: 有时候请求量太大,我们不需要每个请求调用时间,那么可以使用这个参数,指定次数调用后结束。
trace *TestController abc -n 2
[arthas@26932]$ trace *TestController abc -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 66 ms, listenerId: 3
`---ts=2020-08-20 16:29:51;thread_name=http-nio-8080-exec-6;id=1e;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4f936da8
`---[0.2568ms] cn.appblog.arthas.TestController:abc()
+---[0.0362ms] cn.appblog.arthas.User:<init>() #19
+---[0.018ms] cn.appblog.arthas.User:setName() #20
`---[0.018599ms] cn.appblog.arthas.User:setAge() #21
`---ts=2020-08-20 16:30:04;thread_name=http-nio-8080-exec-7;id=1f;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4f936da8
`---[0.394099ms] cn.appblog.arthas.TestController:abc()
+---[0.0449ms] cn.appblog.arthas.User:<init>() #19
+---[0.0302ms] cn.appblog.arthas.User:setName() #20
`---[0.0576ms] cn.appblog.arthas.User:setAge() #21
Command execution times exceed limit: 2, so command will exit. You can set it with -n option.
我们也可以进行筛选,比如我们要找出请求时间大于 10ms 的线程,如下命令即可。
trace *TestController abc '#cost>10'
watch 命令
常用参数:
-b
: 在调用方法前观察这个方法,可以看到传入的参数值
watch -b *TestController abc params
[arthas@26932]$ watch -b *TestController abc params
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms, listenerId: 4
ts=2020-08-20 16:33:04; [cost=0.062801ms] result=@Object[][
@Integer[22],
]
ts=2020-08-20 16:33:10; [cost=0.023ms] result=@Object[][
@Integer[25],
]
-e
: 观察抛出异常时传入参数
watch -e *TestController abc params
[arthas@26932]$ watch -e *TestController abc params
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms, listenerId: 5
ts=2020-08-20 16:34:22; [cost=0.200399ms] result=@Object[][
@Integer[0],
]
ts=2020-08-20 16:34:43; [cost=0.880799ms] result=@Object[][
null,
]
-f
: 方法调用完成,返回对象是观察具体数据
watch -f *TestController abc params
[arthas@26932]$ watch -f *TestController abc params
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 38 ms, listenerId: 6
ts=2020-08-20 16:36:37; [cost=0.0628ms] result=@Object[][
@Integer[22],
]
ts=2020-08-20 16:36:55; [cost=0.6637ms] result=@Object[][
@Integer[0],
]
假设我们想观察详细一些怎么做呢?
先看看我们抛出异常的情况,只是看异常,不看具体堆栈
watch *TestController abc '{params,target,throwExp}'
[arthas@26932]$ watch *TestController abc '{params,target,throwExp}'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 29 ms, listenerId: 7
ts=2020-08-20 16:38:29; [cost=0.278899ms] result=@ArrayList[
@Object[][isEmpty=false;size=1],
@TestController[cn.appblog.arthas.TestController@3d4f4fbf],
@NullPointerException[java.lang.NullPointerException],
]
查看具体堆栈的在后面加-x 2
,意思是输出2
层的结果,默认情况下我们只输出异常(也是就默认-x 1
)
watch *TestController abc '{params,target,throwExp}' -x 2
[arthas@26932]$ watch *TestController abc '{params,target,throwExp}' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 26 ms, listenerId: 8
ts=2020-08-20 16:40:11; [cost=0.1639ms] result=@ArrayList[
@Object[][
null,
],
@TestController[
],
java.lang.NullPointerException
at cn.appblog.arthas.TestController.abc(TestController.java:16)
at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
,
]
可以尝试多种情况,比如将所有参数,返回结果都输出
watch *TestController abc '{params,target,returnObj}' -x 2
[arthas@26932]$ watch *TestController abc '{params,target,returnObj}' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 27 ms, listenerId: 9
ts=2020-08-20 16:41:37; [cost=0.0707ms] result=@ArrayList[
@Object[][
@Integer[22],
],
@TestController[
],
@User[
name=@String[Joe.Ye],
age=@Integer[22],
],
]
stack 命令
该命令霸道,看源码执行方式必备呀。比如:我们看到一个核心方法,但是发现这个方法会被执行的路径很多,我们很难找到到底哪个执行了,那这个命令就体现其强大之处了。
常用命令:
-n
: 指定结束次数,达到次数则自动退出,不继续监听
stack *User setName -n 1
上面那个命令,用我们一个User
类的setName
方法来查看,发现就是我们TestController
调用了。
[arthas@26932]$ stack *User setName -n 1
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 27 ms, listenerId: 10
ts=2020-08-20 16:44:07;thread_name=http-nio-8080-exec-2;id=1a;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4f936da8
@cn.appblog.arthas.User.setName()
at cn.appblog.arthas.TestController.abc(TestController.java:20)
at sun.reflect.GeneratedMethodAccessor20.invoke(null:-1)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/25/arthas-alibaba-online-diagnostic-artifact/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论