前言:
之前陆连续续的分享了 JDK 自带的相关调优命令、图形化界面工具、第三方网站工具等,本篇我们分享一下 Alibaba 开源的工具 Arthas。
JVM 系列文章传送门
初识 JVM(Java 虚拟机)
深入理解 JVM(Java 虚拟机)
一文搞懂 JVM 垃圾接纳(JVM GC)
深入理解 JVM 垃圾接纳算法
一文搞懂 JVM 垃圾收集器
JVM 调优相关参数
JVM 场景面试题【强烈推荐】
JVM 性能调优 – 线上应用 JVM 内存的的预估设置【实战】
JVM 性能调优 – 线上应用 JVM 内存调优【实战】
JVM 性能调优 – 模拟触发 Minor GC【GC 日志分析】
JVM 性能调优 – 模拟触发 Minor GC(2)【GC 日志分析】
JVM 性能调优 – CMS 垃圾接纳器 GC 日志分析【Full GC】
JVM 性能调优 – JVM常用调优工具【jps、jstack、jmap、jstats 命令】
bash: jstack: command not found【jps、jstack、jmap、jstats 命令不生效解决】
JVM 性能调优 – JVM 调优常用工具【jconsole、jvisualvm】
JVM 性能调优 – JVM 调优常用网站
Arthas
Arthas 是一款由阿里巴巴开在 2018 年 9 月开源的 Java 诊断工具,支持 JDK6+,采用命令行交互模式,旨在资助开发者在线上环境中快速定位和解决各种题目,而无需重启 JVM 或修改代码。Arthas 通过命令行交互模式,提供丰富的功能,如检察方法调用的参数、返回值和非常,监控方法实行耗时,定位类加载题目等,大大提升了线上题目排查的服从。
arthas 官方文档
Arthas 使用场景
Arthas 具有强大且丰富的功能,让 Arthas 能做的事变非常多,下面枚举几项常见的使用环境,如下:
- 是否有一个全局视角来检察体系的运行状况?
- 为什么 CPU 又升高了,到底是那里占用了 CPU ?
- 运行的多线程有死锁吗?有壅闭吗?
- 步伐运行耗时很长,是那里耗时比较长呢?如何监测呢?
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有实行到?难道是我没 commit?分支搞错了?
- 遇到题目无法在线上 debug,难道只能通过加日志再重新发布吗?
- 有什么办法可以监控到 JVM 的及时运行状态?
- 有什么办法可以监控到容器和中心件(AliTomcat、HSF、Notify 等)的及时运行状态?
- 怎么快速定位应用的热门,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?
Arthas 下载
arthas jar 包下载地址
arthas jar 包下载地址:https://arthas.aliyun.com/arthas-boot.jar
Window 版本直接点击链接就可以下载了,Linux 下载方式如下:
- curl -O https://arthas.aliyun.com/arthas-boot.jar
复制代码- % Total % Received % Xferd Average Speed Time Time Time Current
- Dload Upload Total Spent Left Speed
- 100 141k 100 141k 0 0 301k 0 --:--:-- --:--:-- --:--:-- 301k
复制代码 启动 Arthas
Arthas 是一个 jar 包,使用 java -jar 命令就可以启动,如下:
- java -jar arthas-boot.jar
复制代码 启动结果如下:
- [INFO] JAVA_HOME: /data/svr/jdk1.8.0_251/jre
- [INFO] arthas-boot version: 4.0.4
- [INFO] Process 114368 already using port 3658
- [INFO] Process 114368 already using port 8563
- [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
- * [1]: 114368 /data/apps/xx-xx-server/xx-xxx-server-V1.6.16.jar
- [2]: 94737 /data/apps/xx-xx-gateway-server/xx-xx-gateway-server-V1.6.9.jar
- [3]: 114684 /data/apps/xx-xx-xx-server/xx-xx-xx-server-V1.6.16.jar
- 1
- [INFO] arthas home: /home/w/.arthas/lib/4.0.4/arthas
- [INFO] The target process already listen port 3658, skip attach.
- [INFO] arthas-client connect 127.0.0.1 3658
- ,---. ,------. ,--------.,--. ,--. ,---. ,---.
- / O \ | .--. ''--. .--'| '--' | / O \ ' .-'
- | .-. || '--'.' | | | .--. || .-. |`. `-.
- | | | || |\ \ | | | | | || | | |.-' |
- `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
- wiki https://arthas.aliyun.com/doc
- tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
- version 4.0.4
- main_class
- pid 114368
- time 2024-11-22 19:58:01.021
复制代码 启动命令中会显示 Arthas 的版本号、占用的 port、以及当前服务器上运行的 Java 应用,1、2、3 是 Java 应用序号 ID(注意不是进程 ID)。
选择 Java 应用序号 ID 就可以进入对应的应用进行操纵,就可以进行 Arthas 相关的操纵了。
Arthas 常用命令
Arthas 功能非常强大,命令也非常多,下面枚举一下分类,如下:
命令作用dashboard
当前体系的及时数据面板thread检察当前 JVM 的线程堆栈信息jvm检察当前 JVM 的信息sysprop检察和修改 JVM 的体系属性getstatic检察类的静态属性sc检察 JVM 已加载的类信息sm检察已加载类的方法信息dumpdump 已加载类的 byte code 到特定目次redefine加载外部的.class文件,redefine 到 JVM 里jad反编译指定已加载类的源码classloader检察 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResourcemonitor方法实行监控watch方法实行数据观测trace方法内部调用路径,并输出方法路径上的每个节点上耗时stack输出当前方法被调用的调用路径tt方法实行数据的时空隧道,记载下指定方法每次调用的入参和返回信息,并能对这些差别的时间下调用进行观测options检察或设置 Arthas 全局开关help检察命令资助信息cls清空当前屏幕区域session检察当前会话的信息reset重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置全部增强过的类version输出当前目标 Java 进程所加载的 Arthas 版本号quit退出当前 Arthas 客户端,其他 Arthas 客户端不受影响shutdown闭 Arthas 服务端,全部 Arthas 客户端全部退出keymapArthas 快捷键列表及自定义快捷键grep搜刮满意条件的结果plaintext将命令的结果去除颜色wc按行统计输出结果jobs列出全部 jobkill逼迫终止任务fg将暂停的任务拉到前台实行bg将暂停的任务放到后台实行 以上就是常用的 Arthas 命令,下面会针对重要的命令进利用用分享。
Arthas 命令实战
dashboard
命令
dashboard
命令可以展示体系的线程、内存等指标,用法如下:
实行结果如下:
- ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON
- 1384 sentinel-time-tick-thread
- main 5 TIMED_WAITING 0.0 0.000 35:25.406 false true
- 129 SimplePauseDetectorThread_0 main 5 TIMED_WAITING 0.0 0.000 4:45.212 false true
- 131 SimplePauseDetectorThread_2 main 5 TIMED_WAITING 0.0 0.000 4:44.681 false true
- 130 SimplePauseDetectorThread_1 main 5 TIMED_WAITING 0.0 0.000 4:43.209 false true
- 9 DataCarrier.DEFAULT.Consumer.0.Thread main 5 TIMED_WAITING 0.0 0.000 2:43.341 false true
- -1 VM Periodic Task Thread - -1 - 0.0 0.000 1:23.083 false true
- 123 com.alibaba.nacos.naming.beat.sender main 5 TIMED_WAITING 0.0 0.000 1:22.915 false true
- -1 VM Thread - -1 - 0.0 0.000 1:13.880 false true
- 8 org.apache.skywalking.apm.dependencies.ka main 5 RUNNABLE 0.0 0.000 1:8.345 false true
- -1 C2 CompilerThread1 - -1 - 0.0 0.000 0:56.791 false true
- -1 C2 CompilerThread0 - -1 - 0.0 0.000 0:55.441 false true
- 53 redisson-timer-6-1 main 5 TIMED_WAITING 0.0 0.000 0:51.060 false false
- 1385 sentinel-system-status-record-task-thread
- main 5 TIMED_WAITING 0.0 0.000 0:49.440 false true
- 47 lettuce-timer-3-1 main 5 TIMED_WAITING 0.0 0.000 0:39.791 false false
- 85 redisson-netty-4-32 main 5 RUNNABLE 0.0 0.000 0:34.329 false false
- 142 DestroyJavaVM main 5 RUNNABLE 0.0 0.000 0:33.481 false false
- 11 SkywalkingAgent-6-JVMService-produce-0 main 5 TIMED_WAITING 0.0 0.000 0:24.079 false true
- Memory used total max usage GC
- heap 755M 1018M 1018M 74.26% gc.ps_scavenge.count 580
- ps_eden_space 321M 333M 335M 96.10% gc.ps_scavenge.time(ms) 7000
- ps_survivor_space 1M 2M 2M 99.76% gc.ps_marksweep.count 1
- ps_old_gen 432M 683M 683M 63.26% gc.ps_marksweep.time(ms) 468
- nonheap 273M 285M 1256M 21.78%
- code_cache 90M 90M 240M 37.57%
- metaspace 163M 173M 512M 31.97%
- compressed_class_space 19M 21M 504M 3.91%
- direct 920K 920K - 100.00%
- mapped 0K 0K - 0.00%
- Runtime
- os.name Linux
- os.version 3.10.0-1160.88.1.el7.x86_64
- java.version 1.8.0_251
- java.home /data/svr/jdk1.8.0_251/jre
- systemload.average 0.00
- processors 4
- timestamp/uptime Fri Nov 22 19:28:55 CST 2024/268655s
复制代码 通过实行结果可以看出有对线程的各项指标监控,也有对内存的各项指标的监控。
thread
命令
thread
命令是检察线程堆栈信息的命令,如法如下:
实行结果如下:
- ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON -1 C2 CompilerThread0 - -1 - 12.11 0.024 0:55.398 false true -1 C1 CompilerThread2 - -1 - 1.83 0.003 0:23.095 false true 1384 sentinel-time-tick-thread
- main 5 TIMED_WAITING 0.78 0.001 35:24.879 false true 42878 arthas-command-execute system 5 RUNNABLE 0.47 0.000 0:0.006 false true -1 VM Thread - -1 - 0.27 0.000 1:13.861 false true 131 SimplePauseDetectorThread_2 main 5 TIMED_WAITING 0.09 0.000 4:44.611 false true 130 SimplePauseDetectorThread_1 main 5 TIMED_WAITING 0.09 0.000 4:43.140 false true 129 SimplePauseDetectorThread_0 main 5 TIMED_WAITING 0.09 0.000 4:45.141 false true 9 DataCarrier.DEFAULT.Consumer.0.Thread main 5 TIMED_WAITING 0.05 0.000 2:43.301 false true -1 VM Periodic Task Thread - -1 - 0.03 0.000 1:23.063 false true 110 http-nio-8188-BlockPoller main 5 RUNNABLE 0.02 0.000 0:6.689 false true 47 lettuce-timer-3-1 main 5 TIMED_WAITING 0.02 0.000 0:39.781 false false 51 Catalina-utility-2 main 1 TIMED_WAITING 0.01 0.000 0:8.267 false false 89 FeignApacheHttpClientConfiguration.connec main 5 TIMED_WAITING 0.01 0.000 0:2.368 false true 16 SkywalkingAgent-10-ProfileSendSnapshotSer main 5 TIMED_WAITING 0.01 0.000 0:12.164 false true 53 redisson-timer-6-1 main 5 TIMED_WAITING 0.01 0.000 0:51.047 false false -1 C2 CompilerThread1 - -1 - 0.01 0.000 0:56.677 false true 50 Catalina-utility-1 main 1 WAITING 0.01 0.000 0:8.455 false false 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.063 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.313 false true 4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true 25 Attach Listener system 9 RUNNABLE 0.0 0.000 0:0.012 false true 42851 arthas-timer system 9 WAITING 0.0 0.000 0:0.000 false true 42854 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.032 false true 42855 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 42856 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.001 false true 42857 arthas-shell-server system 9 TIMED_WAITING 0.0 0.000 0:0.000 false true 42858 arthas-session-manager system 9 TIMED_WAITING 0.0 0.000 0:0.000 false true 42860 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.198 false true 42890 Keep-Alive-Timer system 8 TIMED_WAITING 0.0 0.000 0:0.000 false true 5 SkywalkingAgent-1-LogFileWriter-0 main 5 TIMED_WAITING 0.0 0.000 0:6.006 false true 7 org.apache.skywalking.apm.dependencies.ka main 5 RUNNABLE 0.0 0.000 0:3.767 false true 8 org.apache.skywalking.apm.dependencies.ka main 5 RUNNABLE 0.0 0.000 1:8.330 false true 10 SkywalkingAgent-5-GRPCChannelManager-0 main 5 TIMED_WAITING 0.0 0.000 0:0.488 false true 11 SkywalkingAgent-6-JVMService-produce-0 main 5 TIMED_WAITING 0.0 0.000 0:24.073 false true
复制代码 thread
命令会把全部线程信息展现出来,包括线程 ID、线程名称、线程分组、优先级、线程状态、CPU 的使用率、上次采样之后线程运行增量 CPU 时间(单元:秒)、线程运行总CPU时间(单元:秒)、线程当前的中断状态、是否是 daemon 线程。
thread
另有以下用法:
- thread
-n 3 :输出前 3 个最忙的线程堆栈信息。
- thread
-all: 显示全部的线程相关信息。
- thread
-n 3 -i 1000: 列出1000 ms 内最繁忙的 3 个线程信息的堆栈信息。
- thread
–state: 检察指定状态的线程,(TIMED_WAITI、WAITING、RUNNABLE等)。
- thread
-b:当出现死锁后后,找出壅闭其他线程的线程,,会提示你出现死锁的位置。
thread
-n 3 用法如下:
实行结果如下:
- "sentinel-time-tick-thread" Id=1384 cpuUsage=0.65% deltaTime=1ms time=2149072ms TIMED_WAITING
- at java.lang.Thread.sleep(Native Method)
- at java.lang.Thread.sleep(Thread.java:340)
- at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
- at com.alibaba.csp.sentinel.util.TimeUtil$1.run(TimeUtil.java:37)
- at java.lang.Thread.run(Thread.java:748)
- "arthas-command-execute" Id=42878 cpuUsage=0.5% deltaTime=1ms time=43ms RUNNABLE
- at sun.management.ThreadImpl.dumpThreads0(Native Method)
- at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)
- at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:206)
- at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
- at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
- at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
- at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
- at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
- at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
- at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- at java.lang.Thread.run(Thread.java:748)
复制代码 thread
-all 用法如下:
会打印出全部的线程信息,实行结果如下:
- Threads Total: 211, NEW: 0, RUNNABLE: 67, BLOCKED: 0, WAITING: 88, TIMED_WAITING: 46, TERMINATED: 0, Internal threads: 10 ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON -1 C1 CompilerThread2 - -1 - 2.86 0.005 0:23.325 false true 1384 sentinel-time-tick-thread
- main 5 TIMED_WAITING 0.8 0.001 35:49.203 false true 42878 arthas-command-execute system 5 RUNNABLE 0.34 0.000 0:0.046 false true 131 SimplePauseDetectorThread_2 main 5 TIMED_WAITING 0.11 0.000 4:47.780 false true 129 SimplePauseDetectorThread_0 main 5 TIMED_WAITING 0.11 0.000 4:48.310 false true 1385 sentinel-system-status-record-task-thread
- main 5 TIMED_WAITING 0.1 0.000 0:50.008 false true 130 SimplePauseDetectorThread_1 main 5 TIMED_WAITING 0.1 0.000 4:46.305 false true 124 Timer-1 main 5 TIMED_WAITING 0.08 0.000 0:5.371 false true 9 DataCarrier.DEFAULT.Consumer.0.Thread main 5 TIMED_WAITING 0.07 0.000 2:45.121 false true -1 VM Periodic Task Thread - -1 - 0.04 0.000 1:23.990 false true 47 lettuce-timer-3-1 main 5 TIMED_WAITING 0.02 0.000 0:40.225 false false 1386 sentinel-metrics-record-task-thread-1 main 5 TIMED_WAITING 0.02 0.000 0:12.960 false true 53 redisson-timer-6-1 main 5 TIMED_WAITING 0.01 0.000 0:51.608 false false
复制代码 thread
-n 3 -i 1000 用法如下:
thread
-n 3 -i 1000 实行结果如下:
- "sentinel-time-tick-thread" Id=1384 cpuUsage=0.78% deltaTime=7ms time=2149752ms TIMED_WAITING
- at java.lang.Thread.sleep(Native Method)
- at java.lang.Thread.sleep(Thread.java:340)
- at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
- at com.alibaba.csp.sentinel.util.TimeUtil$1.run(TimeUtil.java:37)
- at java.lang.Thread.run(Thread.java:748)
- "SimplePauseDetectorThread_1" Id=130 cpuUsage=0.11% deltaTime=1ms time=286375ms TIMED_WAITING
- at java.lang.Thread.sleep(Native Method)
- at java.lang.Thread.sleep(Thread.java:340)
- at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
- at org.LatencyUtils.TimeServices.sleepNanos(TimeServices.java:62)
- at org.LatencyUtils.SimplePauseDetector$SimplePauseDetectorThread.run(SimplePauseDetector.java:116)
复制代码 thread
-state 用法如下:
thread
-state 实行结果如下:
- Threads Total: 201, NEW: 0, RUNNABLE: 66, BLOCKED: 0, WAITING: 88, TIMED_WAITING: 47, TERMINATED: 0
- ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON
- 51 Catalina-utility-2 main 1 WAITING 0.02 0.000 0:8.370 false false
- 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.064 false true
- 3 Finalizer system 8 WAITING 0.0 0.000 0:0.316 false true
- 42851 arthas-timer system 9 WAITING 0.0 0.000 0:0.000 false true
- 14 SkywalkingAgent-2-CommandService-0 main 5 WAITING 0.0 0.000 0:0.000 false true
- 38 spring.cloud.inetutils main 5 WAITING 0.0 0.000 0:0.000 false true
- 40 logback-1 main 5 WAITING 0.0 0.000 0:0.149 false true
- 45 Druid-ConnectionPool-Create-50592708 main 5 WAITING 0.0 0.000 0:0.805 false true
- 90 xxl-job, executor TriggerCallbackThread main 5 WAITING 0.0 0.000 0:0.007 false true
- 92 Thread-12 main 5 WAITING 0.0 0.000 0:0.021 false true
复制代码 只贴上了部分线程信息。
thread
-b 用法如下:
thread
-b 实行结果如下:
- No most blocking thread
- found!
复制代码 thread
-b 是用来检察死锁信息的,因为我这里的应用没有死锁,因此看不到死锁信息。
jad 命令的使用
jad 可以反编译类信息,使用 jad 包名.类名 .方法名,即可对指定类进行反编译,如果不传方法名就是反编译整个类,用法如下:
- jad com.xsx.SrpingBootApplication
复制代码 jad 命令实行结果如下:
- ClassLoader:
- +-org.springframework.boot.loader.LaunchedURLClassLoader@44c79f32
- +-sun.misc.Launcher$AppClassLoader@18b4aac2
- +-sun.misc.Launcher$ExtClassLoader@69cb456c
- Location:
- file:/data/apps/xx-xxx-xxx-server/xx-xxx-xxx-server.jar!/BOOT-INF/lib/xx-xxx-xxx-boot-starter.RELEASE.jar!/
- /*
- * Decompiled with CFR.
- *
- * Could not load the following classes:
- * org.springframework.boot.SpringApplication
- * org.springframework.boot.autoconfigure.SpringBootApplication
- * org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- * org.springframework.cloud.openfeign.EnableFeignClients
- */
- package com.xx;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
- import org.springframework.cloud.openfeign.EnableFeignClients;
-
- @EnableFeignClients(basePackages={"com.xx"})
- @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
- public class DigitalApplication {
- public static void main(String[] args) {
- /*18*/ SpringApplication.run(DigitalApplication.class, (String[])args);
- }
- }
- Affect(row-cnt:2) cost in 627 ms.
复制代码 sc 命令
sc命令用于检察 JVM 已加载的类信息,该命令可以搜刮全部已经加载到JVM中的类信息,支持模糊搜刮和详细信息输出,根本用法:sc [class-pattern],此中 class-pattern 可以是类的全限定名或路径名,例如 com.taobao.test.AAA 或 com/taobao/test/AAA,默认环境下,sc 命令会开启子类匹配功能,如果需要准确匹配,可以使用参数 disable-sub-class true,sc 命令的根本用法如下:
- sc -d com.xx.xx.xxx.xxx.web.job.SatxxxJob
复制代码 大概
- sc -d com.xx.xx.xxx.xxx.web.job.Satxxx*
复制代码 命令实行结果如下:
- class-info com.xx.xx.xxx.xx.web.x.SatxxxJob
- code-source file:/data/apps/xx-xx-xxx-server/xx-xxx-xxx-server.jar!/BOOT-INF/classes!/
- name com.xx.xx.xxx.xxx.web.job.SatxxxJob
- isInterface false
- isAnnotation false
- isEnum false
- isAnonymousClass false
- isArray false
- isLocalClass false
- isMemberClass false
- isPrimitive false
- isSynthetic false
- simple-name SatxxxJob
- modifier public
- annotation org.springframework.stereotype.Component
- interfaces
- super-class +-java.lang.Object
- class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@44c79f32
- +-sun.misc.Launcher$AppClassLoader@18b4aac2
- +-sun.misc.Launcher$ExtClassLoader@69cb456c
- classLoaderHash 44c79f32
- class-info com.xx.xx.xxx.xxx.xx.job.SatxxxJob$$EnhancerBySpringCGLIB$$311db573
- code-source file:/data/apps/xx-xxx-xxx-server/xx-xxx-xxx-server-V1.6.16.jar!/BOOT-INF/classes!/
- name com.xx.xx.xxx.xx.web.job.SatxxxJob$$EnhancerBySpringCGLIB$$311db573
- isInterface false
- isAnnotation false
- isEnum false
- isAnonymousClass false
- isArray false
- isLocalClass false
- isMemberClass false
- isPrimitive false
- isSynthetic false
- simple-name SatxxxJob$$EnhancerBySpringCGLIB$$311db573
- modifier public
- annotation
- interfaces org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.cglib.proxy.Factory
- super-class +-com.xx.xx.xx.xxx.xx.job.SatxxxJob
- +-java.lang.Object
- class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@44c79f32
- +-sun.misc.Launcher$AppClassLoader@18b4aac2
- +-sun.misc.Launcher$ExtClassLoader@69cb456c
- classLoaderHash 44c79f32
- Affect(row-cnt:2) cost in 30 ms.
复制代码 sm 命令
sm 命令是 “Search-Method” 的简写,用于搜刮全部已经加载到 JVM 中的方法信息,sm 命令可以资助用户了解某个方法的签名信息,包括方法的返回范例、参数范例以及访问修饰符等,sm 命令的根本用法如下:
- sm java.lang.String toString
复制代码 命令实行结果如下:
- java.lang.String toString()Ljava/lang/String;
- Affect(row-cnt:1) cost in 25 ms.
复制代码 sm -d 命令查询某个方法的详细信息,实行命令如下:
- sm -d java.lang.String toString
复制代码 命令实行结果如下:
- declaring-class java.lang.String
- method-name toString
- modifier public
- annotation
- parameters
- return java.lang.String
- exceptions
- classLoaderHash null
- Affect(row-cnt:1) cost in 31 ms.
复制代码 profiler 命令
profiler 命令可以生成应用的热门火焰图,本质是通过不停的采样,把收集到的采样数据生成火焰图,需要注意的是 profiler 命令目前不知道在 window 体系中运行,profiler 启动命令如下:
profiler 启动命令实行结果:
检察已经采样的数据命令如下:
实行结果如下:
- [arthas@114684]$ profiler getSamples
- 58
复制代码 直接输出了采样的个数。
检察采样状态命令如下:
- [arthas@114684]$ profiler status
- Profiling is running for 258 seconds
复制代码 profiler 制止命令,制止的同时会输出一个 html 文件,可以指定 html 文件的输出路径,实行命令如下:
- [arthas@114684]$ profiler stop
- OK
- profiler output file: /data/apps/xx-xxx-xxx-server/arthas-output/20241124-162013.html
复制代码 实行完 stop 命令后,我们可以通过浏览器检察 profiler 的结果,Arthas 默认使用 3658 端口,我们使用如下方式进行访问:
http://ip:3658/arthas-output/
tt 命令
我在学习使用 Arthas tt 命令时候遇到一些题目,这里先把使用 Arthas tt 命令的注意事项阐明一下,如下:
- tt 命令记载的数据都会在内存中储存着,如果想要整理可以使用 tt --delete-all 命令进行清楚,因为是在内存中存储,建议不要记载太多次数,防止内存被撑爆。
- tt 命令监控 Controller 层的接口时候报如下错误,是因为 Skywalking 探针对 Controller 层进行了方法改写,导致监控失败,我们可以关闭 Skyworking,大概仅监控不受其影响的 service 层接口。
使用 tt 命令监控 Controller 层的接口时候报如下错误:
- Affect(class count: 1 , method count: 1) cost in 213 ms, listenerId: 1
- Enhance error! exception: java.lang.ClassFormatError
- error happens when enhancing class: null, check arthas log: /home/xx/logs/arthas/arthas.log
复制代码 tt 命令是接口时间监控命令,我们可以通过 tt 命令来监控接口的哀求时长,使用如下:
- # 监控DemoController的test()请求时长10次
- tt -t com.xx.xx.xxx.xxx.web.controller.xxxxx.xxxServiceImpl queryxxxList-n 10
复制代码 该命令的意思是监控 xxxController 类的 queryxxxList 调用 3 次的哀求时长,实行结果如下:
- Press Q or Ctrl+C to abort.
- Affect(class count: 2 , method count: 2) cost in 425 ms, listenerId: 2
- INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
- -------------------------------------------------------------------------------------------------------------------------------------
- 1000 2024-11-24 17:02:59 33.81715 true false 0x27f1282 xxxServiceImpl queryxxxList
- .036 2
- 1001 2024-11-24 17:02:59 38.23686 true false 0x58784d71 xxxServiceImpl$$En queryxxxList
- .040 1 hancerBySpringCGLIB$$546bc84b
- 1002 2024-11-24 17:02:59 8.668024 true false 0x27f1282 xxxServiceImpl queryxxxList
- .754
- Command execution times exceed limit: 3, so command will exit. You can set it with -n option.
复制代码 根据实行可以看到,记载 3 次哀求信息后 Arthas 就主动制止了,只要没有手动实行整理数据,数据就会一直缓存在内存中,即使退出 Arthas 也不会清除,我们可以使用 tt -l 命令检察缓存中的哀求信息列表,如下:
- INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
- -------------------------------------------------------------------------------------------------------------------------------------
- 1000 2024-11-24 17:02:59 33.81715 true false 0x27f1282 xxxServiceImpl queryxxxList
- .036 2
- 1001 2024-11-24 17:02:59 38.23686 true false 0x58784d71 xxxServiceImpl$$En queryxxxList
- .040 1 hancerBySpringCGLIB$$546bc84b
- 1002 2024-11-24 17:02:59 8.668024 true false 0x27f1282 xxxServiceImpl queryxxxList
- .754
- Affect(row-cnt:3) cost in 2 ms.
复制代码 tt -i
我们可以使用 tt -i 命令来检察某一次哀求的详细数据,index 就是我们上面的 1000、1001、1002,命令使用如下:
命令实行结果如下:
- INDEX 1000
- GMT-CREATE 2024-11-24 17:02:59.036
- COST(ms) 33.817152
- OBJECT 0x27f1282
- CLASS com.xx.xx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl
- METHOD queryxxxList
- IS-RETURN true
- IS-EXCEPTION false
- PARAMETERS[0] @xxxQueryDTO[
- jobNumber=@String[],
- xxxId=null,
- page=@Page[com.baomidou.mybatisplus.extension.plugins.pagination.Page@614168d4],
- ]
- RETURN-OBJ @Page[
- serialVersionUID=@Long[8545996863226528798],
- records=@ArrayList[isEmpty=false;size=16],
- total=@Long[16],
- size=@Long[20],
- current=@Long[1],
- orders=@ArrayList[isEmpty=true;size=0],
- optimizeCountSql=@Boolean[true],
- isSearchCount=@Boolean[true],
- hitCount=@Boolean[false],
- countId=null,
- maxLimit=null,
- ]
- Affect(row-cnt:1) cost in 9 ms.
复制代码 tt -i 可以帮我们打印出方法收支参的信息。
tt -i -p 哀求重放命令,演示如下:
- RE-INDEX 1000
- GMT-REPLAY 2024-11-24 17:13:48.602
- OBJECT 0x27f1282
- CLASS com.xx.xx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl
- METHOD queryxxxList
- IS-RETURN true
- IS-EXCEPTION false
- PARAMETERS[0] @xxxQueryDTO[
- jobNumber=@String[],
- xxxId=null,
- page=@Page[com.baomidou.mybatisplus.extension.plugins.pagination.Page@614168d4],
- ]
- IS-RETURN true
- IS-EXCEPTION false
- COST(ms) 18.867698
- RETURN-OBJ @Page[
- serialVersionUID=@Long[8545996863226528798],
- records=@ArrayList[isEmpty=false;size=16],
- total=@Long[16],
- size=@Long[20],
- current=@Long[1],
- orders=@ArrayList[isEmpty=true;size=0],
- optimizeCountSql=@Boolean[true],
- isSearchCount=@Boolean[true],
- hitCount=@Boolean[false],
- countId=null,
- maxLimit=null,
- ]
- Time fragment[1000] successfully replayed 1 times.
复制代码 为什么叫命令重放呢?注意看时间,上面的时间是:2024-11-24 17:02:59.036 ,而这次的时间是:2024-11-24 17:13:48.602,这就是重放,不得不感叹 Arthas 的强大。
tt --delete-all 命令是用来清除 tt 命令的缓存数据的,使用如下:
- [arthas@114684]$ tt --delete-all Time fragments are cleaned.Affect(row-cnt:3) cost in 0 ms.[arthas@114684]$ tt -i 1000
- -pTime fragment[1000] does not exist.[arthas@114684]$
复制代码 根据实行结果可以看到,我们使用了 tt --delete-all 名字之后,再进行回放就提示 does not exist 了。
monitor 命令
monitor 命令可以监视一个时间段中指定方法的实行次数,乐成次数,失败次数,用法如下:
- monitor -c 3 com.xx.xx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl queryxxxList
复制代码 上述这个命令是监控 queryxxxList 方法的实行环境,分别统计了统计周期内的总次数、实行乐成次数、实行失败次数、实行均匀耗时,实行失败率,-c 表现的是监控的统计周期(cycle of output)。
实行结果如下:
- 2024-11-24 21:04:1 com.xx.xx.xxx.xxx.web.se queryxxxList 4 4 0 4.24 0.00%
- 1.403 rvice.impl.xxx.xxxImpl
- 2024-11-24 21:04:1 com.xx.xx.xxx.xxx.web.se queryxxxList 4 4 0 4.61 0.00%
- 1.403 rvice.impl.xxx.Home xxxImpl$$Enhanc
- erBySpringCGLIB$$546bc84b
- timestamp class method total success fail avg-rt(ms) fail-rate
-
复制代码 实行结果符合预期,需要注意的是 monitor 命令是一个非及时响应的命令,需要对应的方法有被调用才行,以是需要触发接口哀求才能触发 monitor 效果,触发之后 monitor 命令会按监控的统计周期的时间间隔一直输出监控数据,如果先要退出 monitor 命令,ctrl+c 即可。
stack 命令
stack - 输出当前方法被调用的调用路径, 一个方法被实行的路径非常多,大概说方法的实行分支很多的时候,不知道这个方法是从那里被实行,就可以使用 stack 来输出方法的实行路径,用法如下:
- stack com.xx.xx.xxx.xxx.xx.service.impl.xxx.xxxServiceImpl queryxxxList
复制代码 上述命令的意思是查询 queryxxxList 方法的调用路径,实行结果如下:
stack 命令是一个非及时响应的命令,需要对应的方法有被触发调用,Arthas 才会输出结果。
trace 命令
trace 和 stack 命令有相同之处,都是查找方法的调用链路,但 trace 更强大,可以输出方法路径上的每个节点上的耗时, 对于定位因 RT 高导致的性能题目有极大的资助,用法如下:
- trace com.xx.xxx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl queryxxxList
复制代码 实行结果如下:
- Press Q or Ctrl+C to abort.
- Affect(class count: 2 , method count: 2) cost in 425 ms, listenerId: 4
- `---ts=2024-11-24 21:29:04.471;thread_name=http-nio-8188-exec-87;id=26785;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@2b6fcca1
- `---[35.303516ms] com.xx.xxx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl$$EnhancerBySpringCGLIB$$546bc84b:queryxxxList()
- `---[99.65% 35.181193ms ] org.springframework.cglib.proxy.MethodInterceptor:intercept()
- `---[99.39% 34.968002ms ] com.xx.xxx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl:queryxxxList()
- +---[0.07% 0.025667ms ] com.xx.xxx.xxx.xxx.web.pojo.dto.xxx.xxxQueryDTO:getPage() #45
- `---[99.63% 34.837439ms ] com.xx.xxx.xxx.xxx.web.dao.xxx.xxxMapper:queryxxxList() #45
复制代码 根据实行结果可以看到打印除了方法调用链路上的各个节点的耗时已经耗时占比,非常使用。
trace 命令另有两种常用方法如下:
- #根据调用耗时 过滤出耗时大于 15ms 的调用路径trace com.xx.xxx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl queryxxxList
- '#cost >15'#打印 JDK 的方法调用trace --skipJDKMethod com.xx.xxx.xxx.xxx.web.service.impl.xxx.xxxServiceImpl queryxxxList
复制代码 trace 命令也是一个非及时响应的命令,需要对应的方法有被触发调用,Arthas 才会输出结果。
退出 Arthas
退出 Arthas 使用 stop 命令即可。
总结:本篇简单分享了 Arthas 的常用命令使用方法,Arthas 功能非常强大,有很多功能我又没有使用过,接待各位朋友也补充 Arthas 的相关命令的使用方法,也盼望本篇的分享可以或许资助到正需要的你。
如有不准确的地方接待各位指出纠正。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |