同类工具还有唯品会的VJTop
,二者各有优劣吧,VJTop在内存分析上比Arthas
上要好点。
必须强调一点:JVM自带的jvisualvm
也是一个神器,不过请记得启动的时候在启动脚本中添加相应的参数。
对比于“先top -H 列出线程,再执行jstack拿到全部线程,再手工换算十与十六进制的线程号”的繁琐过程,arthas既方便,又可以连续跟踪,更不会因为jstack造成JVM停顿。
指令:thread -n 3 -i 1000
作用:查看线程占用最高的3个线程,并打印堆栈。
解析:
-n 3
表示是占用最高的3个线程。-i 1000
表示的是1000ms 来进行取样。输出内容:
包括线程以及堆栈信息。
$ thread -n 3
"as-command-execute-daemon" Id=29 cpuUsage=75% RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440)
at com.taobao.arthas.core.command.monitor200.ThreadCommand$1.action(ThreadCommand.java:58)
.....
- java.util.concurrent.ThreadPoolExecutor$Worker@6cd0b6f8
"as-session-expire-daemon" Id=25 cpuUsage=24% TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.taobao.arthas.core.server.DefaultSessionManager$2.run(DefaultSessionManager.java:85)
"Reference Handler" Id=2 cpuUsage=0% WAITING on java.lang.ref.Reference$Lock@69ba0f27
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@69ba0f27
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
现象:
本质:某个线程持有了锁一致不释放,但是其他线程需要这个锁。
指令:thread -b
输出内容:这个线程的堆栈信息
$ thread -b
"http-bio-8080-exec-4" Id=27 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at test.arthas.TestThreadBlocking.doGet(TestThreadBlocking.java:22)
- locked java.lang.Object@725be470 <---- but blocks 4 other threads!
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at test.filter.TestDurexFilter.doFilter(TestDurexFilter.java:46)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doF
指令:jvm
可以查看当前类的信息
有如下几个信息需要注意
如下为垃圾回收的信息:GARBAGE-COLLECTORS
-----------------------------------------------------------------------
GARBAGE-COLLECTORS
-----------------------------------------------------------------------
PS Scavenge 2/18(ms)
[count/time]
PS MarkSweep 0/0(ms)
[count/time]
其中PS Scavenge
指的是Parallel Scavenge
:新生代通过并行线程进行垃圾回收
PS MarkSweep
表示老年带采用的是Parallel Old
$ watch com.taobao.container.Test test "params[0].size()"
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 22 ms.
@Integer[40]
https://github.com/alibaba/arthas/issues/71
trace
:方法内部调用路径,并输出方法路径上的每个节点上耗时
例子:
trace demo.MathGame run
查看demo包下MathGame
这个类的run
方法调用链路
trace -j demo.MathGame run
该指令会过滤调用 jdk
的方法
trace demo.MathGame run '#cost > 10'
该命令添加了一个'#cost > 10 '
表示的是调用耗时超过10ms
的方法
tt
比watch
更好用,主要是用来监视并保存某个方法的调用记录
直接上例子:
tt -t demo.MathGame primeFactors
表示的不停查看方法的调用结果。tt -t -n 3 demo.MathGame primeFactors
表示最多记录3次,因为如果方法被调用太多次,会导致内存撑爆。tt -i 1004 -p
为了避免要求前端重新发送一次 xx 请求,可以利用该指令进行模拟。我们看看这些指令的数据结果是什么:
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-------------------------------------------------------------------------------------------------------------------------------------
1000 2018-12-04 11:15:38 1.096236 false true 0x4b67cf4d MathGame primeFactors
1001 2018-12-04 11:15:39 0.191848 false true 0x4b67cf4d MathGame primeFactors
1002 2018-12-04 11:15:40 0.069523 false true 0x4b67cf4d MathGame primeFactors
1003 2018-12-04 11:15:41 0.186073 false true 0x4b67cf4d MathGame primeFactors
1004 2018-12-04 11:15:42 17.76437 true false 0x4b67cf4d MathGame
其中的参数比较清楚,我就不做解释了。
如果要对内存进行分析,最好还是摘流量后,通过 jvm自带的 jmap dump
后通过MAT
进行分析比较好。
https://github.com/alibaba/arthas/issues?q=label%3Auser-case