一、概述
1、简介
Arthas 是一款基于 Java 开发的开源应用程序诊断工具,可以帮助开发者实时监控和分析 Java 应用程序运行情况,并进行调试和优化。
Arthas 提供了丰富的命令行工具和可视化界面,包括线程堆栈、类加载器、内存使用情况、方法执行时间等多个方面的信息,可以帮助用户快速定位并解决应用程序中的性能问题和异常情况。同时,Arthas 还支持对生产环境中的应用程序进行远程诊断和操作,极大地提高了应用程序的故障排查效率和可靠性。
2、解决问题
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到 JVM 的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从 JVM 内查找某个类的实例?
3、与jstack
、jstat
、jmap
的区别
Arthas、jstack、jstat 和 jmap 都是 Java 调优工具,但它们之间有以下区别:
Arthas 是一款全新的 Java 诊断与调试工具,不仅可以执行传统的 JVM 监控命令,还提供了许多其他高级特性,如实时监控、动态修改代码、反编译等。相比较而言,jstack、jstat 和 jmap 更加基础,只提供了线程栈信息、垃圾回收信息、堆转储信息等。
Arthas 的交互式命令行界面使得开发人员可以通过命令操作来查看和修改目标 JVM 的状态,支持实时监控和动态修改代码,极大地方便了开发和调试过程。而 jstack、jstat 和 jmap 只能通过命令行执行,无法进行实时交互。
Arthas 支持监控线上应用,无需停机,对线上问题快速响应非常有优势。而 jstack、jstat 和 jmap 需要停止 JVM 进程才能进行相关分析。
虽然 Arthas、jstack、jstat 和 jmap 都是 Java 调优工具,但是 Arthas 具有更加强大的功能和交互式的命令行界面,可用于动态修改代码,更适合于在线上环境中进行 JVM 诊断和调试。而 jstack、jstat 和 jmap 更适合本地开发,或者需要停机分析的场景。
4、官方文档
https://arthas.aliyun.com/
二、下载
https://arthas.aliyun.com/arthas-boot.jar
三、快速入门
1、启动 math-game
curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar
math-game
是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。
math-game
源代码:https://github.com/alibaba/arthas/blob/master/math-game/src/main/java/demo/MathGame.java
2、启动 arthas
在命令行下面执行(使用和目标进程一致的用户启动,否则可能 attach 失败):
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
选择应用 java 进程:
C:\Users\scy\Desktop\arthas>java -jar arthas-boot.jar
[INFO] JAVA_HOME: D:\Program Files\java\jdk1.8.0_171\jre
[INFO] arthas-boot version: 3.6.9
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 2072 org.jetbrains.idea.maven.server.RemoteMavenServer36[2]: 11468 org.jetbrains.idea.maven.server.RemoteMavenServer36[3]: 18044 oracle.ide.osgi.boot.OracleIdeLauncher[4]: 21356 org.jetbrains.idea.maven.server.RemoteMavenServer36[5]: 21948 math-game.jar[6]: 268
math-game
进程是第 5个,则输入 5,再输入回车/enter
。Arthas
会 attach
到目标进程上,并输出日志:
[INFO] arthas home: C:\Users\jiuhui-4\.arthas\lib\3.6.9\arthas
[INFO] Try to attach process 21948
[INFO] Attach process 21948 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 3.6.9
main_class
pid 21948
time 2023-06-21 16:20:41[arthas@21948]$
如果出现如下异常:
[ERROR] Can not read arthas version from: arthas.aliyun.com/api/latest_…
[ERROR] Can not find Arthas under local: /root/.arthas/lib and remote repo mirror: aliyun
[ERROR] Unable to download arthas from remote server, please download the full package according to wiki: github.com/alibaba/art…
按照提示到github
上下载完整包。下载地址:https://github.com/alibaba/arthas/releases 到release下载arthas-bin.zip
解压arthas-bin.zip
后,直接运行java -jar arthas-boot.jar
然后输入对应的java
进程序号就可以进行arthas
了。
3、查看 dashboard
输入dashboard
,按回车/enter
,会展示当前进程的信息,按ctrl+c
可以中断执行。
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIM TIME INTERRUPT DAEMON
2 Reference Handler system 10 WAITING 0.0 0.000 0:0.000 false true
3 Finalizer system 8 WAITING 0.0 0.000 0:0.000 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.015 false true
12 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true
15 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0.0 0.000 0:0.015 false true
16 arthas-NettyWebsocketTtyBoots system 5 RUNNABLE 0.0 0.000 0:0.000 false true
17 arthas-NettyWebsocketTtyBoots system 5 RUNNABLE 0.0 0.000 0:0.015 false true
18 arthas-shell-server system 5 TIMED_WA 0.0 0.000 0:0.000 false true
19 arthas-session-manager system 5 TIMED_WA 0.0 0.000 0:0.000 false true
20 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true
Memory used total max usage GC
heap 110M 489M 7234M 1.53% gc.ps_scavenge.count 0
ps_eden_space 110M 128M 2670M 4.14% gc.ps_scavenge.time(ms) 0
ps_survivor_space 0K 21504K 21504K 0.00% gc.ps_marksweep.count 0
ps_old_gen 0K 348160K 0.00% gc.ps_marksweep.time(ms) 0
nonheap 27M 28M -1 97.22%
code_cache 6M 6M 240M 2.55%
metaspace 19M 20M -1 97.15%
compressed_class_space 2M 2M 1024M 0.23%
Runtime
os.name Windows 10
os.version 10.0
java.version 1.8.0_171
java.home D:\Program Files\java\jdk1.8.0_171\jre
systemload.average -1.00
processors 12
timestamp/uptime Wed Jun 21 16:33:43 CST 2023/885s
4、thread 命令
通过 thread
命令来获取到math-game
进程的 Main Class
thread 1
会打印线程 ID 1
的栈,通常是 main
函数的线程。
[arthas@21948]$ thread 1 | grep 'main('at demo.MathGame.main(MathGame.java:17)
5、jad 命令
通过 jad 来反编译 Main Class
[arthas@21948]$ jad demo.MathGameClassLoader:
+-sun.misc.Launcher$AppClassLoader@55f96302+-sun.misc.Launcher$ExtClassLoader@74a14482Location:
/C:/Users/scy/Desktop/arthas/math-game.jar/** Decompiled with CFR.*/package demo;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.TimeUnit;public class MathGame {private static Random random = new Random();private int illegalArgumentCount = 0;public static void main(String[] args) throws InterruptedException {MathGame game = new MathGame();while (true) {
/*16*/ game.run();
/*17*/ TimeUnit.SECONDS.sleep(1L);}}public void run() throws InterruptedException {try {
/*23*/ int number = random.nextInt() / 10000;
/*24*/ List<Integer> primeFactors = this.primeFactors(number);
/*25*/ MathGame.print(number, primeFactors);}catch (Exception e) {
/*28*/ System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());}}public static void print(int number, List<Integer> primeFactors) {StringBuffer sb = new StringBuffer(number + "=");
/*34*/ for (int factor : primeFactors) {
/*35*/ sb.append(factor).append('*');}
/*37*/ if (sb.charAt(sb.length() - 1) == '*') {
/*38*/ sb.deleteCharAt(sb.length() - 1);}
/*40*/ System.out.println(sb);}public List<Integer> primeFactors(int number) {
/*44*/ if (number < 2) {
/*45*/ ++this.illegalArgumentCount;throw new IllegalArgumentException("number is: " + number + ", need >= 2");}ArrayList<Integer> result = new ArrayList<Integer>();
/*50*/ int i = 2;
/*51*/ while (i <= number) {
/*52*/ if (number % i == 0) {
/*53*/ result.add(i);
/*54*/ number /= i;
/*55*/ i = 2;continue;}
/*57*/ ++i;}
/*61*/ return result;}}Affect(row-cnt:1) cost in 432 ms.
[arthas@21948]$
6、watch 命令
通过watch
命令来查看demo.MathGame#primeFactors
函数的返回值:
[arthas@21948]$ watch demo.MathGame primeFactors returnObj
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 66 ms, listenerId: 1
method=demo.MathGame.primeFactors location=AtExit
ts=2023-06-21 16:43:40; [cost=0.7314ms] result=@ArrayList[@Integer[2],@Integer[7],@Integer[13159],
]
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-06-21 16:43:41; [cost=0.1341ms] result=null
method=demo.MathGame.primeFactors location=AtExit
ts=2023-06-21 16:43:42; [cost=0.4295ms] result=@ArrayList[@Integer[3],@Integer[14197],
]
更多的功能可以查看进阶使用:https://arthas.aliyun.com/doc/advanced-use.html
01、查看某个方法的参数、返回值、抛出的异常。
watch 全类名 方法名 returnObj
// 查看方法的返回值
watch 全类名 方法名 '{params, throwExp}' -e
// 查看参数和异常,方法名支持 通配符 *,-e表示只捕获抛出异常时的请求,后面还以跟 -x 2,-x表示“对象层级”。
02、设置输出json格式。
options json-format true
//设置以json格式输出。
7、退出 arthas
如果只是退出当前的连接,可以用quit
或者exit
命令。Attach
到目标进程上的 arthas
还会继续运行,端口会保持开放,下次连接时可以直接连接上。
如果想完全退出 arthas
,可以执行stop
命令。
8、命令总汇
1)help
:查看所有可用的 Arthas
命令和说明。
2)jvm
:查看当前 JVM 的相关信息,包括堆大小、GC 策略、线程数等。
3)classloader
:查看和操作类加载器信息,包括已加载的类、类加载器层级等。
4)thread
(cpu占用过高/死锁):查看和操作线程状态和堆栈信息,包括线程数量、状态、阻塞信息等。
5)trace
(方法耗时及跟踪 ):跟踪指定方法的执行情况,输出方法参数、返回值、耗时等信息。
6)watch
(查看函数的参数/返回值/异常信息):监控指定方法的执行情况,当指定条件满足时自动触发相应的操作。
7)sc
:查看和操作 Spring 上下文信息,包括 Bean 定义、Bean 生命周期等。
8)sql
:查看和操作数据库连接和 SQL 执行情况,支持常见的 JDBC 驱动程序。
9)dashboard
(内存泄漏):启动 Arthas 的可视化界面,展示当前应用程序的各种运行情况。
10) jad
:反编译源代码
11)tt
:
-
发现异常并查看异常
tt -t com.UserServiceImpl check
//记录方法调用信息tt -i 1001
//上面指令发现异常后,查看异常tt -i 1001 -p
//重新调用,重现异常 -
查看、更新类成员变量值
ognl '@com.Arthas@hashSet'
//查看ognl ‘@com.Arthas@hashSet.add(“test”)’ //更新
四、参考
JVM调优神器,运用 Arthas 释放 Java应用性能的全部潜力
https://juejin.cn/post/7234545968094773307
Arthas
https://blog.csdn.net/weixin_42061487/article/details/120520260
ARTHAS进阶学习(常用命令)
https://www.cnblogs.com/theRhyme/p/10659265.html