1. 下载
1、在 Arthas-github 地址里选择一个版本下载arthas-bin.zip
2、解压arthas-bin.zip
之后文件夹里会有arthas-boot.jar
包
2. 启动
1、通过CMD命令窗口执行查看java进程的PID
D:\Arthas>tasklist | findstr java
java.exe 16340 Console 1 369,632 K
java.exe 2740 Console 1 316,380 K
java.exe 3956 Console 1 449,008 K
java.exe 18216 Console 1 334,500 K
java.exe 18088 Console 1 625,728 K
java.exe 19140 Console 1 172,368 K
java.exe 19100 Console 1 232,520 K
java.exe 20892 Console 1 402,052 K
java.exe 21812 Console 1 345,044 K
java.exe 28996 Console 1 317,676 K
java.exe 27968 Console 1 619,448 K
java.exe 24340 Console 1 15,528 K
java.exe 18148 Console 1 644,692 K
java.exe 30340 Console 1 96,456 K
D:\Arthas>
2、选择一个PID,执行arthas-boot.jar
启动命令
D:\Arthas>java -jar arthas-boot.jar 27968
[INFO] JAVA_HOME: C:\Program Files\Java\jdk1.8.0_251\jre
[INFO] arthas-boot version: 4.0.5
[INFO] arthas home: D:\Arthas
[INFO] Try to attach process 27968
[INFO] Attach process 27968 success.
[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.5
main_class com.test.example.TestApplication
pid 27968
start_time 2025-03-31 15:46:47.939
currnt_time 2025-04-01 14:30:35.380[arthas@27968]$
到这里就表示进入了arthas的操作台,可以输入对应的指令查看JVM数据,命令列表
3、如果需要监控多个java进程,需要指定端口启动
java -jar arthas-boot.jar <PID1> --telnet-port 9998 --http-port 9999
java -jar arthas-boot.jar <PID2> --telnet-port 8888 --http-port 8889
3. arthas 常用命令
3.1 dashboard
dashboard
是一个综合性的命令,它会显示 JVM 的实时状态数据面板,包括以下内容:
[arthas@27968]$ dashboard
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON
207 DestroyJavaVM main 5 RUNNABLE 0.0 0.000 0:22.640 false false
300 sentinel-metrics-record-task-thread-1 main 5 TIMED_WAITING 0.0 0.000 0:12.453 false true
198 grpc-nio-worker-ELG-1-8 main 5 RUNNABLE 0.0 0.000 0:12.078 false true
96 grpc-nio-worker-ELG-1-6 main 5 RUNNABLE 0.0 0.000 0:11.796 false true
33 grpc-nio-worker-ELG-1-2 main 5 RUNNABLE 0.0 0.000 0:11.500 false true
58 grpc-nio-worker-ELG-1-4 main 5 RUNNABLE 0.0 0.000 0:11.156 false true
21 com.alibaba.nacos.client.auth.ram.identify.watcher.0 main 5 TIMED_WAITING 0.0 0.000 0:7.015 false true
299 sentinel-system-status-record-task-thread-1 main 5 TIMED_WAITING 0.0 0.000 0:6.656 false true
-1 C1 CompilerThread3 - -1 - 0.0 0.000 0:5.796 false true
110 rpcMergeMessageSend_RMROLE_1_1 main 5 TIMED_WAITING 0.0 0.000 0:5.046 false true
117 redisson-timer-4-1 main 5 TIMED_WAITING 0.0 0.000 0:3.984 false false
176 lettuce-timer-6-1 main 5 TIMED_WAITING 0.0 0.000 0:2.640 false true
-1 VM Thread - -1 - 0.0 0.000 0:2.578 false true
103 NettyClientSelector_TMROLE_1_1 main 5 RUNNABLE 0.0 0.000 0:2.000 false true
154 NettyClientSelector_RMROLE_1_1 main 5 RUNNABLE 0.0 0.000 0:1.750 false true
94 com.alibaba.nacos.client.remote.worker main 5 TIMED_WAITING 0.0 0.000 0:1.421 false true
196 com.alibaba.nacos.client.remote.worker main 5 TIMED_WAITING 0.0 0.000 0:1.281 false true
30 com.alibaba.nacos.client.remote.worker main 5 TIMED_WAITING 0.0 0.000 0:1.250 false true
181 http-nio-9404-exec-2 main 5 WAITING 0.0 0.000 0:1.125 false true
56 com.alibaba.nacos.client.remote.worker main 5 TIMED_WAITING 0.0 0.000 0:1.109 false true
180 http-nio-9404-exec-1 main 5 WAITING 0.0 0.000 0:1.109 false true
121 redisson-netty-2-4 main 5 RUNNABLE 0.0 0.000 0:0.703 false false
-1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.703 false true
119 redisson-netty-2-2 main 5 RUNNABLE 0.0 0.000 0:0.656 false false
-1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.625 false true
123 redisson-netty-2-6 main 5 RUNNABLE 0.0 0.000 0:0.609 false false
-1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.593 false true
-1 GC task thread#5 (ParallelGC) - -1 - 0.0 0.000 0:0.593 false true
-1 GC task thread#8 (ParallelGC) - -1 - 0.0 0.000 0:0.578 false true
-1 GC task thread#9 (ParallelGC) - -1 - 0.0 0.000 0:0.578 false true
-1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.578 false true
-1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.562 false true
-1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.562 false true
-1 GC task thread#3 (ParallelGC) - -1 - 0.0 0.000 0:0.546 false true
-1 GC task thread#4 (ParallelGC) - -1 - 0.0 0.000 0:0.531 false true
131 redisson-netty-2-14 main 5 RUNNABLE 0.0 0.000 0:0.515 false false
133 redisson-netty-2-15 main 5 RUNNABLE 0.0 0.000 0:0.437 false false
124 redisson-netty-2-7 main 5 RUNNABLE 0.0 0.000 0:0.421 false false
135 redisson-netty-2-17 main 5 RUNNABLE 0.0 0.000 0:0.421 false false
134 redisson-netty-2-18 main 5 RUNNABLE 0.0 0.000 0:0.406 false false
155 tableMetaChecker_1_1 main 5 TIMED_WAITING 0.0 0.000 0:0.406 false true
190 http-nio-9404-Poller main 5 RUNNABLE 0.0 0.000 0:0.390 false true
Memory used total max usage GC
heap 256M 648M 3580M 7.16% gc.ps_scavenge.count 47
ps_eden_space 126M 388M 1330M 9.49% gc.ps_scavenge.time(ms) 1123
ps_survivor_space 2M 2M 2M 89.92% gc.ps_marksweep.count 4
ps_old_gen 127M 257M 2685M 4.76% gc.ps_marksweep.time(ms) 479
nonheap 166M 175M -1 94.97%
code_cache 30M 30M 240M 12.76%
metaspace 120M 128M -1 94.18%
compressed_class_space 15M 16M 1024M 1.50%
direct 151K 151K - 100.00%
mapped 0K 0K - 0.00%
Runtime
os.name Windows 10
os.version 10.0
java.version 1.8.0_251
java.home C:\Program Files\Java\jdk1.8.0_251\jre
systemload.average -1.00
processors 12
timestamp/uptime Tue Apr 01 14:35:32 CST 2025/82123s
3.1.1【线程信息】
你看到的线程列表显示了每个线程的运行状态:
ID 和 NAME:线程的唯一标识和名称,例如 Reference Handler, Finalizer 等。这些是 JVM 的系统线程,用于管理资源清理、垃圾回收等。
GROUP:线程所属的线程组。
PRIORITY:线程的优先级(范围为 1 到 10,优先级高的线程会获得更多 CPU 时间)。
STATE:线程当前的状态,例如:
RUNNABLE:线程正在运行或准备运行。
WAITING:线程在等待其他操作完成。
TIMED_WAITING:线程在等待指定的时间结束。
%CPU:线程的 CPU 使用率,当前所有线程使用率为 0.0%,没有消耗大量资源。
INTERRUPT 和 DAEMON:是否为守护线程,以及是否可以被中断。
3.1.2【内存使用情况】
Heap (堆内存):
当前堆内存使用量是 271M,总分配是 624M,上限是 3580M。
GC 信息:
ps_scavenge.count: 小型垃圾回收 (Young GC) 的次数为 45。
ps_marksweep.count: 大型垃圾回收 (Full GC) 的次数为 4。
Non-Heap (非堆内存):包括代码缓存、元空间等非堆区域:
Metaspace:管理类的元数据,使用率很高(94.43%)。
Code Cache:JVM 内存区域,用于存储编译后的字节码。
3.1.3【运行时信息】
OS 信息:运行环境是 Windows 10。
JVM 信息:使用的是 Java 1.8.0_251。
处理器数:系统有 12 个处理器。
如何分析这些数据
当前的应用运行状态比较稳定,CPU 和内存的使用率都处于较低水平。
如果你发现某个线程的 STATE 是 BLOCKED 或 WAITING 且占用高 CPU,可以通过命令 thread 深入查看该线程的调用堆栈。
内存中的 ps_old_gen 占用较低,表明系统没有出现明显的内存泄漏。
如果垃圾回收耗时过长(比如 Full GC 的时间高),可能需要优化内存分配。
3.2 thread
thread
命令用于分析 JVM 中线程的详细信息,帮助你排查线程相关问题,例如性能瓶颈、锁竞争或死锁。
[arthas@27968]$ thread
Threads Total: 197, NEW: 0, RUNNABLE: 56, BLOCKED: 0, WAITING: 79, TIMED_WAITING: 45, TERMINATED: 0, Internal threads: 17
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON
66084 arthas-command-execute system 5 RUNNABLE 7.47 0.015 0:0.015 false true
2 Reference Handler system 10 WAITING 0.0 0.000 0:0.062 false true
3 Finalizer system 8 WAITING 0.0 0.000 0:0.078 false true
4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true
5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.093 false true
15 RMI TCP Accept-0 system 5 RUNNABLE 0.0 0.000 0:0.000 false true
3.2.1【总体线程统计】
这部分告诉你 JVM 中线程的数量及它们的状态:
Threads Total: 总线程数量为 197 个。
NEW: 没有新创建但未启动的线程。
RUNNABLE: 有 56 个线程处于运行状态或等待 CPU 时间片。
BLOCKED: 没有线程处于阻塞状态(竞争锁资源时进入此状态)。
WAITING: 有 79 个线程处于等待状态(等待某个事件的发生)。
TIMED_WAITING: 有 45 个线程处于限时等待状态。
TERMINATED: 没有线程处于终止状态。
Internal threads: JVM 自身管理的线程数量为 17 个。
这些状态反映了线程的生命周期和行为,能帮助你了解系统是否存在线程瓶颈或死锁问题。
3.2.2【详细数据】
DELTA_TIME
含义:线程在最近一段时间内(自上次命令运行以来)消耗的 CPU 时间。
用途:帮助你观察线程的短期行为。如果某个线程的 DELTA_TIME 值突然增加,说明它在这段时间内消耗了大量 CPU,可以深入分析其运行状态。
TIME
含义:线程自创建以来累计消耗的 CPU 时间(以秒为单位)。
用途:用于判断线程是否长期占用大量 CPU。如果某个线程的累计时间过高,可能需要进一步监控它是否有性能问题。
INTERRUPTED
含义:标志线程是否被中断过(true 表示被中断过,false 表示未被中断)。
用途:线程中断通常用于取消长时间运行的任务。如果线程被频繁中断,可能需要检查中断的原因是否合理。
DAEMON
含义:指示线程是否是守护线程(true 表示是守护线程,false 表示不是)。
守护线程:是一种特殊的线程,它的生命周期依赖于 JVM。如果没有非守护线程运行,守护线程会随着 JVM 的退出而结束。
用途:守护线程通常用于后台任务,比如垃圾回收器或定时器线程。非守护线程更重要,因为它们需要手动管理。
3.2.3 利用 CPU 数据分析性能问题
- %CPU:显示每个线程的 CPU 使用率。例如:
如果某线程的 %CPU 持续高于预期(例如超过 80%),可能需要深入分析它的堆栈(用 thread <线程ID> 命令),找出耗时的方法。 - DELTA_TIME:反映短期内线程行为的变化。如果某线程在短时间内有较大的 DELTA_TIME,可能是性能热点。
- TIME:累积时间帮助你识别长期占用资源的线程。
3.2.4 如何进一步分析
1、定位 CPU 使用较高的线程: 用 thread -n 5 查看占用 CPU 前 5 的线程,分析它们的堆栈:
thread -n 5
2、查看特定线程的详细堆栈: 如果某线程状态异常或使用率较高,可以通过 ID 查看其堆栈信息:
thread 66084
3、分析阻塞情况: 如果发现 BLOCKED 线程,可以用以下命令跟踪它们的锁争夺情况:
thread -b
通过这些数据,可以:
- 快速检查线程是否存在性能问题(如高 CPU 使用率或长时间等待)。
- 排查潜在的线程死锁或阻塞问题。
- 分析 JVM 内部线程的状态,判断是否正常运行。
3.3 jvm
功能:显示 JVM 的基本信息,包括版本、启动时间、操作系统信息等。
使用场景:查看 JVM 运行环境。
命令:
jvm
3.4 heapdump
功能:生成堆转储文件,用于分析内存问题。
使用场景:诊断内存泄漏或分析内存使用情况。
命令:
heapdump [生成文件路径]/dumpfile.hprof
3.4.1 打开 hprof 文件
生成的.hprof
文件是没办法直接打开查看的,需要用其他工具打开,这里使用 VisualVM 打开。
启动 VisualVM:
- 在命令行输入
jvisualvm
启动工具。
在 VisualVM 中选择 File > Load,加载 .hprof 文件。 - 功能:可以查看对象分布、线程状态和内存使用情况。
3.4.2 分析 hprof 文件
1. 堆内存的对象分布
在工具中,你通常会看到类似以下信息:
对象类型:列出了堆中各类对象,比如 java.lang.String, java.util.ArrayList, com.example.MyClass。
对象数量:表示每种类型对象的实例数量。
内存占用:显示每种类型对象消耗的内存大小。
分析:
如果某些对象数量异常多(比如数十万或数百万),可能存在内存泄漏问题。
对象占用内存过大时,需要检查代码逻辑是否存在重复创建或未释放资源。
2. GC 根路径
堆转储文件会显示每个对象的引用关系,以及它是否可以被垃圾回收。
GC Roots:是那些无法被回收的对象,比如线程、类加载器、静态变量等。
引用链:展示从 GC Roots 到其他对象的路径。
分析:
如果某对象应该被回收,但它依然被 GC Roots 引用,可能导致内存泄漏。
你可以检查代码是否错误地持有对象的引用。
3. 对象分配情况
堆转储工具(如 Eclipse MAT)会生成报告,比如:
Top Consumers:显示占用最多内存的类。
Histogram:展示内存中的对象类型及分布。
分析:
重点查看内存消耗最大的类,以及它们是否正常。
如果某些类占用内存过高,可能需要优化相关代码。
4. 死锁和线程问题
部分工具会在 .hprof 文件中标记线程的状态和锁信息:
检查线程是否出现死锁。
分析线程是否过多占用内存。
5. 常见问题排查
内存泄漏:寻找那些引用链异常长、占用内存巨大且数量异常的对象。
缓存过大:某些缓存类如 HashMap 或 List 可能存储了过多数据。
未释放资源:比如文件流、数据库连接等。
3.5 memory
功能:查看 JVM 的内存使用情况,包括堆、非堆、GC 等详细信息。
使用场景:监控内存,排查内存不足或 GC 频繁问题。
命令:
memory
Memory used total max usage
heap 430M 589M 3580M 12.01%
ps_eden_space 293M 325M 1323M 22.15%
ps_survivor_space 6M 6M 6M 92.73%
ps_old_gen 130M 257M 2685M 4.87%
nonheap 167M 176M -1 95.00%
code_cache 31M 31M 240M 12.95%
metaspace 120M 128M -1 94.18%
compressed_class_space 15M 16M 1024M 1.50%
direct 151K 151K - 100.00%
mapped 0K 0K - 0.00%
1. 堆内存 (Heap)
堆是 JVM 用于存储对象实例的主要内存区域。
used
(已使用内存):当前堆中已分配的内存大小,这里是430M
。total
(已分配总内存):堆内存的当前容量,这里是589M
。max
(最大容量):堆内存的最大可用大小,这里是3580M
。usage
(使用率):当前堆内存的使用百分比,这里是 12.01%。
分析:当前堆内存的使用率较低(仅 12%),说明内存压力不大。
2. 堆内存细分区域
堆内存通常分为以下几个区域:
a. PS Eden Space
eden
空间:新创建的对象通常会分配在 Eden 空间中。used
:293M
,total
:325M
,max
:1323M
。usage
: 22.15%。- 分析:当前 Eden 空间占用较高,可能是短期内创建了大量新对象。
b. PS Survivor Space
survivor
空间:从 Eden 区域中存活下来的对象会被移入 Survivor 空间。used
:6M
,total
:6M
,max
:6M
。usage
: 92.73%。- 分析:Survivor 空间几乎满了,表明存活对象较多,可能会触发垃圾回收(Minor GC),并将存活对象移入 Old Gen。
c. PS Old Gen
- 老年代:存放生命周期较长的对象。
used
:130M
,total
:257M
,max
:2685M
。usage
: 4.87%。- 分析:老年代的使用率较低,说明长生命周期的对象不多,系统目前压力不大。
3. 非堆内存 (Non-Heap)
非堆内存用于存储类元数据、方法区、JIT 编译器等数据。
used
:167M
,total
:176M
,max
:-1
(-1
表示没有固定上限)。usage
: 95.00%。- 分析:非堆内存的使用率较高,特别是元空间(Metaspace),需要关注是否有类加载过多的问题。
a. Code Cache
- 代码缓存:存储 JIT 编译后的代码。
used
:31M
,total
:31M
,max
:240M
。usage
: 12.95%。- 分析:代码缓存使用率较低,JIT 编译的压力不大。
b. Metaspace
- 元空间:存储类元数据。
used
:120M
,total
:128M
,max
:-1
(没有固定上限)。usage
: 94.18%。- 分析:元空间使用率较高,可能是由于加载了大量类。如果持续增加,可能会导致内存不足。
c. Compressed Class Space
- 压缩类空间:存储元空间中对象类的相关信息。
used
:15M
,total
:16M
,max
:1024M
。usage
: 1.50%。- 分析:使用率较低,没有内存压力。
4. Direct 和 Mapped 内存
这些是 JVM 外部的直接内存分配:
- Direct:直接内存,通常用于 NIO 操作。
- **
used
:151K
,total
:151K
,使用率为 100%。
- **
- Mapped:映射内存。
used
:0K
,没有占用。
分析:Direct 内存使用量很小,但已达到分配限制,如果需要更多直接内存,可以调整 JVM 参数。
3.6 trace
功能:跟踪方法执行路径,显示调用栈及每个方法的耗时。
使用场景:分析性能热点,检查某个方法的执行时间。
命令:
trace com.example.service.UserService getUser
3.7 watch
功能:实时监控方法调用,展示方法的入参、出参和返回值。
使用场景:跟踪方法的运行情况,分析具体数据。
命令:
watch com.example.service.UserService getUser '{params, returnObj}' -x 3
3.8 jad
功能:反编译类文件,显示其源代码。
使用场景:检查动态生成的类或查看某些代码实现。
命令:
jad com.example.controller.UserController
3.9 logger
功能:动态修改日志级别。
使用场景:无需重启应用即可调整日志级别。
命令:
logger
logger com.example.service.UserService debug
3.10 classloader
功能:查看类加载器的信息和加载的类。
使用场景:分析类加载器问题,例如类冲突或类重复加载。
命令:
classloader
3.11 redefine
功能:替换已经加载的类文件,支持热更新。
使用场景:动态更新代码,无需重启应用。
命令:
redefine /path/to/YourClass.class
3.12 perf
功能:监控方法执行性能,查看热点方法的 CPU 和执行时间。
使用场景:优化性能,定位慢方法。
命令:
perf