Arthas

一、简介

Arthas是 阿里巴巴开源的一款 Java 线上诊断工具,利用Arthas可以对指定的JVM进程进行CPU、内存、线程、死锁监控处理,同时也可以动态的获取JVM中的源代码结构。得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。当你遇到以下类似问题而束手无策时,Arthas都可以帮助你解决:

1. 全局JVM运行时监控,CPU、线程、内存、堆栈信息等;

2. CPU彪高,是什么造成的

3. 接口没有反应,卡住了,是不是死锁?

4. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

5. 接口太慢,要优化一下,如何准确找出耗时的代码

6. 写的代码没有执行,是部署的分支不对,还是没有提交

7. 线止有一个低级错误,改起来很简单,能不能在不重启应用的情况下,进行类替换,热部署。

8. 是否有一个全局视角来查看系统的运行状况和JVM 的实时运行状态

二、使用Windows

1. 启动项目

2. 启动arthas

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

输入需要监控的项目编号即可进入Arthas命令行

三、常用命令

1. 监控应用程序性能

使用Arthas可以监控Java应用程序的各个方面,包括线程、内存使用情况、方法调用等。通过监控,可以找出应用程序中存在的性能瓶颈。

1)dashboard:启动实时性能仪表板

运行所有的线程大致信息(名称、状态、CPU占比、是否是守护线程)、JVM运行时堆栈使用状态和垃圾回收状态、系统信息

1. heap:
427M:堆内存的当前使用量。
721M:堆内存的最大容量。
3623M:堆内存的总容量。
11.81%:堆内存的使用率。
这部分提供了关于堆内存的信息。堆内存是用于存储 Java 对象的内存区域,它被分为不同的部分,包括新生代(Eden 和 Survivor)和老年代(Old Gen)。这些数据表示了堆内存的使用情况。

2. gc.ps_scavenge.count:垃圾回收事件的次数,通常与新生代(Eden 和 Survivor)的垃圾回收有关。
43:新生代垃圾回收事件的次数。

3. ps_eden_space:新生代中的 Eden 区域的内存使用情况。
361M:当前使用量。
391M:最大容量。
1263M:总容量。
28.64%:使用率。

4. gc.ps_scavenge.time(ms):新生代垃圾回收事件的总持续时间。
240:总持续时间(以毫秒为单位)。

5. ps_survivor_space:新生代中的 Survivor 区域的内存使用情况。
0K:当前使用量。
48128K:最大容量。
48128K:总容量。
0.00%:使用率。

6. gc.ps_marksweep.count:垃圾回收事件的次数,通常与老年代的垃圾回收有关。
4:老年代垃圾回收事件的次数。

7. ps_old_gen:老年代内存的使用情况。
66M:当前使用量。
282M:最大容量。
2717M:总容量。
2.43%:使用率。

8. nonheap:非堆内存的使用情况。
124M:当前使用量。
129M:最大容量。
-1:总容量("-1" 表示未限制)。
96.32%:使用率。

9. code_cache:代码缓存的使用情况。
18M:当前使用量。
18M:最大容量。
240M:总容量。
7.76%:使用率。

10. metaspace:元空间(Metaspace)的使用情况。
93M:当前使用量。
97M:最大容量。
-1:总容量("-1" 表示未限制)。
95.95%:使用率。

11. compressed_class_space:压缩类空间的使用情况。
12M:当前使用量。
13M:最大容量。
1024M:总容量。
1.23%:使用率。
View Code

2)thread:查看线程详细信息

包括线程堆栈、线程状态等。

1. 查看指定线程堆栈
thread 101

2. 最忙的n个线程并打印堆栈
thread -n 3

3. 找出阻塞其它线程的线程
thread -b

4. 查找所有等待状态的线程
thread --state WAITING
View Code

3)jvm 查看当前 JVM 信息

CLASS-LOADING(类加载):
LOADED-CLASS-COUNT:已加载的类的数量。
TOTAL-LOADED-CLASS-COUNT:总加载的类的数量。
UNLOADED-CLASS-COUNT:已卸载的类的数量。
IS-VERBOSE:类加载是否启用了详细日志。
这一部分提供了关于类加载器和已加载的类的信息。

COMPILATION(编译):
NAME:编译器的名称。
TOTAL-COMPILE-TIME:总编译时间(以毫秒为单位)。
这一部分提供了与编译器性能和编译时间有关的信息。

GARBAGE-COLLECTORS(垃圾回收器):
PS Scavenge 和 PS MarkSweep:这部分提供了两个垃圾回收器的信息,包括它们的名称、垃圾回收事件的次数和持续时间。

MEMORY-MANAGERS(内存管理器):
列出了不同的内存管理器,包括 CodeCacheManager 和 Metaspace Manager,以及与它们相关的内存区域。

MEMORY(内存):
HEAP-MEMORY-USAGE:堆内存使用情况,包括初始大小、已使用、已分配和最大大小。
NO-HEAP-MEMORY-USAGE:非堆内存使用情况,包括初始大小、已使用、已分配和最大大小。
PENDING-FINALIZE-COUNT:待 finalizer 处理的对象数量。
这一部分提供了有关堆内存和非堆内存的详细信息。

OPERATING-SYSTEM(操作系统):
OS:操作系统名称。
ARCH:操作系统架构。
PROCESSORS-COUNT:可用的处理器核心数。
LOAD-AVERAGE:系统的平均负载。
VERSION:操作系统版本。
这一部分提供了有关操作系统的信息。

THREAD(线程):
COUNT:当前线程数。
DAEMON-COUNT:守护线程的数量。
PEAK-COUNT:线程数的峰值。
STARTED-COUNT:已启动的线程总数。
DEADLOCK-COUNT:死锁的线程数量。
这一部分提供了与线程管理和线程数有关的信息。

FILE-DESCRIPTOR(文件描述符):
MAX-FILE-DESCRIPTOR-COUNT:最大文件描述符数量。
OPEN-FILE-DESCRIPTOR-COUNT:已打开文件描述符的数量。
这一部分提供了与文件描述符管理和打开文件的数量有关的信息。
View Code

2. 分析应用程序性能瓶颈

通过Arthas的分析工具,可以深入分析应用程序的性能瓶颈。例如,可以通过分析应用程序的GC日志,找出可能导致内存泄漏或过度GC的代码段。

1)profiler:收集有关方法级别执行时间、方法调用次数等性能数据(为Linux命令,在正式环境上执行会增加负载,生产环境不建议使用)

火焰图是基于perf结果产生的svg图片,用来展示CPU的调用栈

1. 进入 Profiler 模式,开始监视目标应用程序的性能:
profiler start
2. profiler提供可支持的事件
profiler list 
3. 查询目前已获取了多少个可分析样本
profiler getSamples
4. 这将显示已收集的性能数据,包括方法执行时间、方法调用次数等
profiler status
5. 分析性能数据:
分析性能数据以确定性能瓶颈。你可以使用 profiler top 命令来查看最耗时的方法,例如:
profiler top
6. 停止Profiler,会自动在目录下生成svg图片文件,或指定类型文件
profiler stop
profiler stop --format html
View Code

2)watch:监视表达式的值,实时用于实时观察变量或方法或类的执行状况,很常用!!!!!!!!!!。watch <表达式>

-b 在方法调用之前观察
-e 在方法异常后观察
-s 在方法返回之后观察
-f 在方法结束之后观察(默认)
-E 开启正则表达式匹配
-x: 指定输出结果的属性遍历深度,默认为1

1. 观察AuthController类中postAccessToken方法 入参 和 出参,结果属性遍历深度为2层
watch com.chain.controller.AuthController postAccessToken "{params,returnObj}" -x 2
2. 在方法执行前,观察AuthController类中postAccessToken方法 入参 和 出参,结果属性遍历深度为2层
watch com.chain.controller.AuthController postAccessToken "{params,returnObj}" -x 2 -b
3. 观察当前对象中的所有成员变量
watch com.chain.controller.AuthController postAccessToken "target." -x 2 -b
4. 观察当前对象中的某个成员变量
watch com.chain.controller.AuthController postAccessToken "target.number" -x 2 -b
5. 同时观察方法调用前和方法返回后,参数里-n 2,表示只执行两次
watch com.chain.controller.AuthController postAccessToken "{params,target,returnObj}" -x 2 -b -s -n 2
6. 通过条件表达式,输出第1个参数等于null的情况
watch com.chain.controller.AuthController postAccessToken "{params[0],returnObj}" "params[0]=null"
7. 监视变量的值:
watch com.example.MyClass myVariable
这会实时监视 com.example.MyClass 类中名为 myVariable 的变量的值。
8. 监视方法的返回值:
watch com.example.MyClass myMethod returnObj
这会实时监视 com.example.MyClass 类中名为 myMethod 的方法的返回值。
9. 监视静态变量的值:
watch -s com.example.MyClass myStaticVariable
这会实时监视 com.example.MyClass 类中的静态变量 myStaticVariable 的值。
10. 使用条件表达式:
你还可以使用条件表达式来监视某个条件是否满足,例如:
watch 'com.example.MyClass.isInitialized() == true'
这会实时监视条件 com.example.MyClass.isInitialized() == true 是否为真。
11. 监视集合的大小:
watch 'com.example.MyClass.myList.size()'
这会实时监视 com.example.MyClass 类中名为 myList 的集合的大小。
12. 监视数组元素:
watch 'com.example.MyClass.myArray[0]'
这会实时监视 com.example.MyClass 类中名为 myArray 的数组的第一个元素的值。
13. 自定义输出格式:
你可以使用 -x 选项来自定义输出的格式,例如:
watch -x 'com.example.MyClass.myField.toString()'
这会以自定义的格式显示监视结果。
14. 停止监视:
要停止监视,可以使用 unwatch 命令,例如:
unwatch com.example.MyClass myVariable
这会停止对 myVariable 的监视。
View Code

3)monitor:监控指定类中方法的执行情况

执行总数,成功数,失败数,平均相应时间等。monitor <类路径> <方法名>

1. 监控postAccessToken方法,默认120s输出一次
monitor com.chain.controller.AuthController postAccessToken

2. 监控postAccessToken方法,5s统计输出一次
monitor com.chain.controller.AuthController postAccessToken -c 5
View Code

3. 诊断代码问题

使用Arthas可以实时查看应用程序的运行状态和执行轨迹,从而可以快速定位代码中的问题。例如,可以查看方法的调用情况、查看方法的入参和出参,以及查看类的加载情况等。

1)jad:反编译类文件(.class -> .java)

把字节码文件反编译成源代码,jad <类名>

jad --source-only com.chain.controller.AuthController > D:\\AuthController.java

1. 反编译类(包含类加载器和路径):
jad com.example.MyClass
这会尝试反编译 com.example.MyClass 类的字节码,并显示其源代码。

2. 反变异类中的方法
jad com.example.MyClass Test

3. 只看源代码
jad --source-only com.chain.controller.AuthController

4. 指定输出文件:
你可以使用 -o 选项来指定反编译后的源代码输出到文件中,例如:
jad -o /path/to/output/file.java com.example.MyClass
这将把源代码输出到指定的文件中,而不是在命令行中显示。

5. 反编译内部类:
如果类包含内部类,你可以使用 $ 符号来指定内部类的名称,例如:
jad com.example.MyClass$InnerClass
这会反编译名为 InnerClass 的内部类。

6. 反编译静态内部类:
静态内部类的名称中包含 $ 符号,你可以使用类似的方式来指定静态内部类的名称。

7. 反编译匿名内部类:
匿名内部类的名称通常较长和复杂,你可以查看类的内部结构来确定匿名内部类的名称,然后使用 jad 命令来反编译它。
View Code

2)mc:编译文件(.java -> .class)

在内存中把.java源代码编译成.class字节码文件,mc <文件路径>

1. 编译后.class文件直接回到原来地方
mc D:/Hello.java
2. 指定编译后.class文件放在哪里
mc D:/Hello.java -d D:/
View Code
3)redefine:替换字节码

把新生成的.class字节码文件redefine到JVM中,redefine <类名> <字节码文件路径>

  • a. 原字节码替换后无法恢复,
  • b. 不能新增字段和方法,
  • c. 和jad、watch,trace,monitor、tt等命令冲突,执行完redefine后,如果再执行上述命令,则会把redefine的字节码重置。
  • d. 正在跑的函数,你去redefine,这时函数没有执行完没有退出,则redefine不会马上生效,只有方法完全执行完后,redefine的代码才会生效。
redefine com.example.MyClass /path/to/new/MyClass.class
View Code

4)dump:将已加载类的字节码文件 保存到特定目录: logs/arthas/classdump/

dump java.lang.String
View Code

5)classloader:查看类加载器的信息

classLoader命令将JVM中所有的classloader的信息统计出来,并展示继承树,urls等

可以让指定的classloader去getResources,打印出所有查找到的resources的url,对于ResourceNotFoundException异常比较有用。

-l 按类加载实例进行统计

-a 列出所有ClassLoader加载的类(继承树),请谨慎使用

-c ClassLoader的hashcode

-c -r 用ClassLoader找到某个类的字节码文件在哪个jar包里

-c -load 使用ClassLoader加载某个类
View Code

6)trace:跟踪方法的调用链,及方法执行耗时,非常常用!!!!!!!!!!!!

用于分析方法的执行情况。trace <类名> <方法名>

class-pattern 类名表达匹配
method-pattern 方法名表达式匹配
condition-express 条件表达式,使用OGNL表达式
E 开启正则表达式匹配,默认是通配符匹配
n: 设置命令执行次数
#cost 方法执行耗时,单位是毫秒

1. 追踪方法的执行:
trace com.example.MyClass myMethod
2. 追踪方法的执行,只执行2次
trace com.example.MyClass myMethod -n 2
3. 追踪方法的执行(包含JDK的方法,如random、print等)
trace --skipJDKMethod false com.chain.controller.AuthController postAccessToken
4. 只展示大于某个时间的方法
trace com.chain.controller.AuthController aaaaa '#cost > 0.1'
5. 指定追踪深度:
默认情况下,trace 命令会显示方法调用链的前三层。你可以使用 -n 选项来指定追踪的深度,例如:
trace -n 5 com.example.MyClass myMethod
这会显示方法调用链的前五层。
6. 追踪静态方法:
如果要追踪静态方法,你可以使用 -s 选项,例如:
trace -s com.example.MyClass myStaticMethod
这会追踪 com.example.MyClass 类中名为 myStaticMethod 的静态方法的执行。
7. 停止追踪:
要停止追踪,你可以在任何时间输入 q(quit)并按 Enter 键,或者使用 untrace 命令来停止追踪,例如:
untrace com.example.MyClass myMethod
这会停止对 myMethod 的追踪。
8. 显示方法参数和返回值:
默认情况下,trace 命令会显示方法的参数和返回值。你可以使用 -E 选项来关闭显示参数和返回值,例如:
trace -E com.example.MyClass myMethod
这会在追踪中不显示参数和返回值。
View Code

7)stack:输出当前方法被调用的整个调用路径/堆栈信息,非常常用!!!!!!!!!!!!

输出当前方法被调用的整个调用路径 stack <线程ID>

class-pattern 类名表达匹配
method-pattern 方法名表达式匹配
condition-express 条件表达式,使用OGNL表达式
E 开启正则表达式匹配,默认是通配符匹配
n: 设置命令执行次数
#cost 方法执行耗时,单位是毫秒

1. 追踪aaaaa方法
stack com.chain.controller.AuthController aaaaa
2. 追踪aaaaa方法,当第一个参数为null时,且只追踪2次
stack com.chain.controller.AuthController aaaaa 'params[0]=null' -n 2
3. 追踪aaaaa方法,当执行时间>0.5毫秒时,且只追踪2次
stack com.chain.controller.AuthController aaaaa '#cost>0.5' -n 2
View Code

8)tt:记录跟踪方法每次调用的入参、返回信息和执行时间,用于找到性能瓶颈。类似watch,但是更详细,非常常用!!!!!!!!!!!!

time-tunnel:tt <类名> <方法名>

-t 记录某个方法在一个时间段中的使用
-l 显示所有已经记录的列表(包含索引号)
-n 只记录多少次
-s 搜索表达式
-i 查看指定索引号的详细调用信息
-p 重新发起调用指定的索引号时间碎片

1. 追踪指定方法
tt -t com.chain.controller.AuthController postAccessToken
2. 追踪指定方法,若有重载方法/或者参数类型不同/或者指定参数入参值
tt -t com.chain.controller.AuthController postAccessToken params.length=1
tt -t com.chain.controller.AuthController postAccessToken 'params[1] instanceof Integer'
tt -t com.chain.controller.AuthController postAccessToken 'params[1] == "123"'
3. 显示历史所有追踪记录
tt -l
4. 在现有结果历史中搜索历史追踪记录
tt -s 'method.name=="postAccessToken"'
5. 查看指定索引号的详细调用信息(有入参和返回值)
tt -i 1003
6. 针对某个索引号,再主要重新再发起3次调用
tt -i 1006 -p --replay-times 3
View Code

8)getstatic:实时获取类的静态属性(废弃)

trace <类名> <静态属性名>

getstatic demo.MathGame random
View Code

9)ognl 执行一条ognl表达式对象图导航语言,可以代替getstatic(可执行)很强大!!!!!!!!!!!!!!

ognl <OGNL表达式>

1. express 调用静态函数
ognl '@java.lang.System@out.println("11111")'

2. 获取静态类的静态字段
ognl '@demo.MathGame@random'

3. 执行多行表达式,赋值给临时变量,返回一个List
ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
View Code
4. 其它

1)sc 查看 JVM 已加载的类信息

1. 查看是否加载
sc com.chain.controller.AuthController

2. 显示详细信息
sc com.chain.controller.AuthController -d

3. 显示详细信息,并显示成员变量
sc com.chain.controller.AuthController -d -f
View Code

2)sm 查看已加载类的方法信息

1. 查看类的所有方法
sm com.chain.controller.AuthController

2. 查看是否加载方法
sm com.chain.controller.AuthController postAccessToken

3. 查看方法的详情信息
sm com.chain.controller.AuthController postAccessToken -d
View Code

3)quit, exit 退出,但未结束会话

4)stop 完全退出,结束会话

5)cat 查看任何文本文件内容

6)grep 匹配查找,只能用于管道功能

sysprop | grep java -m 10 最大显示行数10行

7)pwd 展示当前路径

8)cls 清除屏幕

9)session 查看当前会话的信息

10)reset 重置增强类,将被arthas增强过的类全部还原(如被追踪trace

11)version arthas版本

12)sysenv java虚拟机环境属性

13)sysprop 查看和修改JVM的系统属性(可以修改临时的系统属性

View Code

14)vmoption 查看和修改JVM的参数

15)options 查看和修改arthas全局环境变量

1. 获取所有选项
options
2. 获取单项
options json-format
3. 修改选项
options save-result true
View Code

16)heapdump:生成堆转储文件,用于分析内存问题。

heapdump /path/to/dump.hprof

然后通过C:\Program Files\Java\jdk1.8.0_281\bin\jvisualvm.exe来加载hprof文件

 

posted @ 2023-09-21 21:23  yifanSJ  阅读(168)  评论(0编辑  收藏  举报