arthas 可以方便的查看Java程序的运行状况,jvm 参数,堆栈信息,线程情况,可以观察方法执行情况(返回值,参数,执行时间,调用链),可以反编译class 文件,查找class文件,内存编译Java文件,热更新class 文件。
1 arthas 的 下载启动:
下载地址:点击下载
解压下载后的压缩包:unzip arthas-packaging-3.6.0-bin.zip
备注:arthas 的 zip包的根目录里面没有文件夹包裹所有的文件(我非常讨厌这种做法,直接解压整个目录都是乱七八糟的文件),建议先建一个arthas 文件夹在,然后包 zip 放到 arthas 文件夹里面去解压 。
解压后得到这样一个文件目录,arthas-boot.jar 就是启动类jar 包
-rw-r--r--. 1 root root 8458 Sep 27 2020 arthas-agent.jar -rw-r--r--. 1 root root 141885 Sep 27 2020 arthas-boot.jar -rw-r--r--. 1 root root 430937 Sep 27 2020 arthas-client.jar -rw-r--r--. 1 root root 13244556 Sep 27 2020 arthas-core.jar -rw-r--r--. 1 root root 13500149 Apr 21 20:29 arthas-packaging-3.6.0-bin.zip -rw-r--r--. 1 root root 531 Sep 27 2020 arthas.properties -rw-r--r--. 1 root root 5441 Sep 27 2020 arthas-spy.jar -rw-r--r--. 1 root root 41111542 Apr 21 22:36 arthas-tunnel-server-3.6.0-fatjar.jar -rwxr-xr-x. 1 root root 3113 Sep 27 2020 as.bat -rwxr-xr-x. 1 root root 7744 Sep 27 2020 as-service.bat -rwxr-xr-x. 1 root root 33257 Sep 27 2020 as.sh drwxr-xr-x. 2 root root 113 Sep 27 2020 async-profiler -rwxr-xr-x. 1 root root 635 Sep 27 2020 install-local.sh drwxr-xr-x. 2 root root 108 Sep 27 2020 lib -rw-r--r--. 1 root root 2020 Sep 27 2020 logback.xml -rw-r--r--. 1 root root 4490 Sep 27 2020 math-game.jar -rw-------. 1 root root 12543 Apr 21 23:29 nohup.out [root@192 arthas]#
2 启动 java -jar arthas-boot.jar ,然后 可以选择你需要 观察的 Java 程序 ,通过程序编号 选择你要观察的程序,专业说法 叫做 attach,我这里有个别的Java程序,如果没有Java程序就没,我这里输入 1 选择这个程序
3 dashboard 能看到 Java程序运行的总体情况
ID NAME GROUP PRIORIT STATE %CPU DELTA_T TIME INTERRUP DAEMON -1 C1 CompilerThread3 - -1 - 0.25 0.012 0:5.533 false true 670 Timer-for-arthas-dashboa system 5 RUNNABL 0.21 0.010 0:0.045 false true -1 C2 CompilerThread2 - -1 - 0.21 0.010 0:8.212 false true 668 arthas-NettyHttpTelnetBo system 5 RUNNABL 0.09 0.004 0:0.079 false true -1 VM Periodic Task Thread - -1 - 0.06 0.003 0:7.121 false true -1 C2 CompilerThread1 - -1 - 0.06 0.002 0:8.587 false true 18 lettuce-timer-3-1 main 5 TIMED_W 0.03 0.001 0:5.518 false true -1 VM Thread - -1 - 0.01 0.000 0:3.203 false true 14 Catalina-utility-1 main 1 WAITING 0.01 0.000 0:1.164 false false 15 Catalina-utility-2 main 1 TIMED_W 0.01 0.000 0:1.157 false false -1 C2 CompilerThread0 - -1 - 0.01 0.000 0:9.458 false true 19 http-nio-80-Poller main 5 RUNNABL 0.0 0.000 0:0.678 false true 17 mysql-cj-abandoned-conne main 5 TIMED_W 0.0 0.000 0:0.302 false true 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.020 false true Memory used total max usage GC heap 136M 224M 235M 57.84% gc.copy.count 234 eden_space 36M 62M 65M 56.42% gc.copy.time(ms) 940 survivor_space 5M 7M 8M 70.89% 8 tenured_gen 93M 154M 162M 57.76% gc.marksweepcompact.time 1025 nonheap 126M 140M -1 89.98% (ms) code_cache 18M 21M 240M 7.72% metaspace 95M 102M -1 93.04% compressed_class_spa 12M 16M 1024M 1.20% ce direct 88K 88K - Runtime os.name Linux os.version 3.10.0-1160.el7.x86_64 java.version 1.8.0_321 java.home /tools/jdk1.8.0_321/jre systemload.average 0.04 processors 8 timestamp/uptime Thu Apr 21 12:31:20 EDT 2022/11147s
4 thread 能看到线程的 情况 ,thread 线程id 查看指定线程
[arthas@2380]$ thread Threads Total: 39, NEW: 0, RUNNABLE: 10, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 7, TERMINATED: 0, I nternal threads: 7 ID NAME GROUP PRIORIT STATE %CPU DELTA_T TIME INTERRUP DAEMON -1 C1 CompilerThread3 - -1 - 0.4 0.000 0:5.658 false true 669 arthas-command-execute system 5 RUNNABL 0.2 0.000 0:0.005 false true -1 VM Thread - -1 - 0.14 0.000 0:3.210 false true -1 VM Periodic Task Thread - -1 - 0.06 0.000 0:7.158 false true 18 lettuce-timer-3-1 main 5 TIMED_W 0.04 0.000 0:5.540 false true 17 mysql-cj-abandoned-conne main 5 TIMED_W 0.04 0.000 0:0.304 false true -1 C2 CompilerThread2 - -1 - 0.01 0.000 0:8.251 false true -1 C2 CompilerThread0 - -1 - 0.01 0.000 0:9.518 false true -1 C2 CompilerThread1 - -1 - 0.01 0.000 0:8.642 false true 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.020 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.031 false true 4 Signal Dispatcher system 9 RUNNABL 0.0 0.000 0:0.000 false true 27 Attach Listener system 9 RUNNABL 0.0 0.000 0:0.035 false true 658 arthas-timer system 9 WAITING 0.0 0.000 0:0.000 false true 661 arthas-NettyHttpTelnetBo system 5 RUNNABL 0.0 0.000 0:0.016 false true 662 arthas-NettyWebsocketTty system 5 RUNNABL 0.0 0.000 0:0.001 false true 663 arthas-NettyWebsocketTty system 5 RUNNABL 0.0 0.000 0:0.000 false true 664 arthas-shell-server system 9 TIMED_W 0.0 0.000 0:0.000 false true 665 arthas-session-manager system 9 TIMED_W 0.0 0.000 0:0.000 false true 666 arthas-UserStat system 9 WAITING 0.0 0.000 0:0.000 false true 668 arthas-NettyHttpTelnetBo system 5 RUNNABL 0.0 0.000 0:0.137 false true 14 Catalina-utility-1 main 1 TIMED_W 0.0 0.000 0:1.174 false false 15 Catalina-utility-2 main 1 WAITING 0.0 0.000 0:1.165 false false 16 container-0 main 5 TIMED_W 0.0 0.000 0:0.056 false false 19 http-nio-80-Poller main 5 RUNNABL 0.0 0.000 0:0.683 false true 20 http-nio-80-Acceptor main 5 RUNNABL 0.0 0.000 0:0.013 false true 21 DestroyJavaVM main 5 RUNNABL 0.0 0.000 0:4.917 false false 22 http-nio-80-exec-1 main 5 WAITING 0.0 0.000 0:0.612 false true 23 HikariPool-1 housekeeper main 5 TIMED_W 0.0 0.000 0:0.077 false true 25 http-nio-80-exec-2 main 5 WAITING 0.0 0.000 0:0.081 false true 26 http-nio-80-exec-3 main 5 WAITING 0.0 0.000 0:0.022 false true 41 http-nio-80-exec-4 main 5 WAITING 0.0 0.000 0:0.083 false true
5 watch com.lomi.controller.DBController singleThread 观察 com.lomi.controller.DBController 的 singleThread 方法执行情况,键入命令后会在方法被调用的时候打印 信息
[arthas@2380]$ watch com.lomi.controller.DBController singleThread Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 296 ms, listenerId: 1 method=com.lomi.controller.DBController.singleThread location=AtExit ts=2022-04-21 12:36:11; [cost=8.628837ms] result=@ArrayList[ @Object[][isEmpty=false;size=1], @DBController[com.lomi.controller.DBController@1595edc2], @String[OK], ] method=com.lomi.controller.DBController$$EnhancerBySpringCGLIB$$69e8184c.singleThread location=AtExit ts=2022-04-21 12:36:11; [cost=47.392699ms] result=@ArrayList[ @Object[][isEmpty=false;size=1], @DBController$$EnhancerBySpringCGLIB$$69e8184c[com.lomi.controller.DBController@1595edc2], @String[OK], ]
6 trace com.lomi.controller.DBController singleThread 方法的调用追踪,很容易我们看到最耗时的那个调用链
[arthas@2380]$ watch com.lomi.controller.DBController singleThread Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 95 ms, listenerId: 2 [arthas@2380]$ trace com.lomi.controller.DBController singleThread Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 112 ms, listenerId: 3 `---ts=2022-04-21 12:38:26;thread_name=http-nio-80-exec-3;id=1a;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@37ceb1df `---[7.788003ms] com.lomi.controller.DBController$$EnhancerBySpringCGLIB$$69e8184c:singleThread() `---[7.57214ms] org.springframework.cglib.proxy.MethodInterceptor:intercept() `---[6.365406ms] com.lomi.controller.DBController:singleThread() +---[min=0.006531ms,max=0.037131ms,total=0.043662ms,count=2] com.lomi.entity.in.ExecuteIn:getExecuteCount() #42 +---[0.143873ms] com.lomi.entity.Goods:randomGoods() #43 `---[5.976028ms] com.lomi.service.GoodsService:add() #43
7 tt -t com.lomi.controller.DBController singleThread 保持每次调用的 瞬时状况,用于后期调试, tt -l,查看这些记录
[arthas@2380]$ tt com.lomi.controller.DBController singleThread Error during processing the command: java.lang.IllegalArgumentException, message:Argument(s) is/are expected, type 'help tt' to read usage, please check $HOME/logs/arthas/arthas.log for more details. [arthas@2380]$ tt -t com.lomi.controller.DBController singleThread Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 90 ms, listenerId: 4 INDE TIMESTAMP COST( IS-RE IS-E OBJECT CLASS METHOD X ms) T XP ---------------------------------------------------------------------------------------------------- 1000 2022-04-21 12: 5.499 true fals 0x1595edc DBController singleThread 41:30 476 e 2 1001 2022-04-21 12: 9.749 true fals 0x3548698 DBController$$Enhancer singleThread 41:30 468 e 9 BySpringCGLIB$$69e8184 c 1002 2022-04-21 12: 4.897 true fals 0x1595edc DBController singleThread 41:31 25 e 2 1003 2022-04-21 12: 5.880 true fals 0x3548698 DBController$$Enhancer singleThread 41:31 299 e 9 BySpringCGLIB$$69e8184 c 1004 2022-04-21 12: 4.885 true fals 0x1595edc DBController singleThread 41:31 893 e 2 1005 2022-04-21 12: 5.830 true fals 0x3548698 DBController$$Enhancer singleThread 41:31 181 e 9 BySpringCGLIB$$69e8184 c
查询某一次的信息 tt -i index
[arthas@2380]$ tt -i 1001 INDEX 1001 GMT-CREATE 2022-04-21 12:41:30 COST(ms) 9.749468 OBJECT 0x35486989 CLASS com.lomi.controller.DBController$$EnhancerBySpringCGLIB$$69e8184c METHOD singleThread IS-RETURN true IS-EXCEPTION false PARAMETERS[0] @ExecuteIn[ serialVersionUID=@Long[-3418074600644269522], executeCount=@Integer[1], ] RETURN-OBJ @String[OK] Affect(row-cnt:1) cost in 3 ms.
8 cs 查找class文件
jad 反编译class 文件
mc 内存编译
retransform,redefine 热更新 编译好的 class 文件到jvm (并且可以指定 classLoader)
9 heapdump 生成 堆内存dump 文件
10 vmtool --action foreGc 强制执行GC
11 sysprop 查询 和修改 系统配置
12 sysenv 查看系统环境,不能修改
13 vmoption 查看和修改 jvm 的一些参数例如 HeapDumpBeforeFullGC,更多 jvm 参数 可以桶jvm 命令 查看
[arthas@2380]$ vmoption KEY VALUE ORIGIN WRITEABLE ---------------------------------------------------------------------------------------------------- HeapDumpBeforeFullGC false DEFAULT true HeapDumpAfterFullGC false DEFAULT true HeapDumpOnOutOfMemoryEr false DEFAULT true ror HeapDumpPath DEFAULT true CMSAbortablePrecleanWai 100 DEFAULT true tMillis CMSWaitDuration 2000 DEFAULT true CMSTriggerInterval -1 DEFAULT true PrintGC false DEFAULT true PrintGCDetails false DEFAULT true PrintGCDateStamps false DEFAULT true PrintGCTimeStamps false DEFAULT true PrintGCID false DEFAULT true PrintClassHistogramBefo false DEFAULT true reFullGC PrintClassHistogramAfte false DEFAULT true rFullGC PrintClassHistogram false DEFAULT true MinHeapFreeRatio 40 DEFAULT true MaxHeapFreeRatio 70 DEFAULT true PrintConcurrentLocks false DEFAULT true UnlockCommercialFeature false DEFAULT true s
14 memory 查看 jvm 内存情况
[arthas@2380]$ memory Memory used total max usage heap 141M 224M 235M 59.82% eden_space 2M 62M 65M 4.25% survivor_space 7M 7M 8M 95.38% tenured_gen 130M 154M 162M 80.27% nonheap 152M 158M -1 95.91% code_cache 22M 22M 240M 9.29% metaspace 114M 119M -1 96.07% compressed_class_space 14M 16M 1024M 1.45% direct 80K 80K - 100.01% mapped 0K 0K - 0.00%
15 arthas 可以通过浏览器(web console)直接返回
java -jar arthas-boot.jar --target-ip 本机IP 不指定端口默认 8563
16 java -jar arthas-boot.jar --target 192.168.1.200 --password 123 指定密码,然后网页登陆 和 命令行登陆以后都需要输入密码 (不指定用户名默认是 arthas,不输入用户名默认也是 arthas,如果你只是想设一个密码 )
17 现在官方建议我们使用 arthas tunnel ,相当 一堆 arthas 都连接到 arthas tunnel 上,然后 arthas tunel 页面课通过 arthas 连接 arthas tunel 产生的 agentID 连接不同 arthas 节点
需要先启动 arthas tunnel server(默认server端口8080,代理端口7777) ,然后 arthas 在 通过 7777端口连接 tunel server 。tunel server 类似 web console,只是能管理多个 arthas。
18 arthas 可以直接嵌入到 Java程序里面去
1 加入依赖
<!-- arthas 监控人插件 --> <dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <version>3.6.0</version> </dependency>
2 指定 application.yml arthas 的端口
#启动arthas编译调试跟踪问题 arthas: ip: 0.0.0.0 http-port: 8563
3 如果是 springboot 内嵌容器启动 需要 暴露 endpoint (不是内嵌容器的不需要),arthas web console 命令行是使用 websocket ,所以需要这样做。
<!-- websocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.5.5</version> </dependency>
package com.lomi.websocket; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * * @author ZHANGYUKUN * */ @Configuration public class WebsocketExporter { /** * 必须有这个 @ServerEndpoint 才生效,ServerEndpointExporter 会把检查并注册 @ServerEndpoint (如果不是内嵌的tomcat,是外置的tomcat,不需要这个) * @return */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }