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%:使用率。
2)thread:查看线程详细信息
包括线程堆栈、线程状态等。

1. 查看指定线程堆栈 thread 101 2. 最忙的n个线程并打印堆栈 thread -n 3 3. 找出阻塞其它线程的线程 thread -b 4. 查找所有等待状态的线程 thread --state WAITING

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:已打开文件描述符的数量。 这一部分提供了与文件描述符管理和打开文件的数量有关的信息。
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
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 的监视。
3)monitor:监控指定类中方法的执行情况
执行总数,成功数,失败数,平均相应时间等。monitor <类路径> <方法名>

1. 监控postAccessToken方法,默认120s输出一次 monitor com.chain.controller.AuthController postAccessToken 2. 监控postAccessToken方法,5s统计输出一次 monitor com.chain.controller.AuthController postAccessToken -c 5

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 命令来反编译它。
2)mc:编译文件(.java -> .class)
在内存中把.java源代码编译成.class字节码文件,mc <文件路径>

1. 编译后.class文件直接回到原来地方 mc D:/Hello.java 2. 指定编译后.class文件放在哪里 mc D:/Hello.java -d D:/
把新生成的.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
4)dump:将已加载类的字节码文件 保存到特定目录: logs/arthas/classdump/

dump java.lang.String
5)classloader:查看类加载器的信息
classLoader命令将JVM中所有的classloader的信息统计出来,并展示继承树,urls等
可以让指定的classloader去getResources,打印出所有查找到的resources的url,对于ResourceNotFoundException异常比较有用。

-l 按类加载实例进行统计 -a 列出所有ClassLoader加载的类(继承树),请谨慎使用 -c ClassLoader的hashcode -c -r 用ClassLoader找到某个类的字节码文件在哪个jar包里 -c -load 使用ClassLoader加载某个类

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 这会在追踪中不显示参数和返回值。
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
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
8)getstatic:实时获取类的静态属性(废弃)
trace <类名> <静态属性名>

getstatic demo.MathGame random
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}'
1)sc 查看 JVM 已加载的类信息

1. 查看是否加载 sc com.chain.controller.AuthController 2. 显示详细信息 sc com.chain.controller.AuthController -d 3. 显示详细信息,并显示成员变量 sc com.chain.controller.AuthController -d -f
2)sm 查看已加载类的方法信息

1. 查看类的所有方法 sm com.chain.controller.AuthController 2. 查看是否加载方法 sm com.chain.controller.AuthController postAccessToken 3. 查看方法的详情信息 sm com.chain.controller.AuthController postAccessToken -d
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的系统属性(可以修改临时的系统属性)

14)vmoption 查看和修改JVM的参数
15)options 查看和修改arthas全局环境变量

1. 获取所有选项 options 2. 获取单项 options json-format 3. 修改选项 options save-result true
16)heapdump:生成堆转储文件,用于分析内存问题。
heapdump /path/to/dump.hprof
然后通过C:\Program Files\Java\jdk1.8.0_281\bin\jvisualvm.exe来加载hprof文件