java诊断神器arthas简单使用指南

470 阅读5分钟

下载启动

下载地址:arthas.aliyun.com/doc/downloa…

启动:java -Dfile.encoding=UTF-8 -jar ./arthas-boot.jar然后选择要附着的进程

arthas依赖JDK,因此在服务器上需要安装JDK

输入help命令获取帮助文档

注意:从jdk21开始,java提供了一个参数-XX:+EnableDynamicAgentLoading来显示启用动态加载agent(该版本默认启用),并可能将在22及以后的版本默认禁用动态加载agent。

见JEP 451:openjdk.org/jeps/451

常用命令

jvm 查看JVM相关信息

## 查看某容器应用
[arthas@1]$ jvm
 RUNTIME                                                                                                                                                                                                             
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MACHINE-NAME                                                 1@cbms-app-sit-79565b798d-dq88b                                                                                                                        
 JVM-START-TIME                                               2023-09-29 13:04:47                                                                                                                                    
 MANAGEMENT-SPEC-VERSION                                      1.2                                                                                                                                                    
 SPEC-NAME                                                    Java Virtual Machine Specification                                                                                                                     
 SPEC-VENDOR                                                  Oracle Corporation                                                                                                                                     
 SPEC-VERSION                                                 1.8                                                                                                                                                    
 VM-NAME                                                      OpenJDK 64-Bit Server VM                                                                                                                               
 VM-VENDOR                                                    Oracle Corporation                                                                                                                                     
 VM-VERSION                                                   25.222-b10                                                                                                                                             
## JVM接收的参数
 INPUT-ARGUMENTS                                              -javaagent:/app/skywalking-agent/skywalking-agent.jar                                                                                                  
                                                              -Dfile.encoding=UTF-8                                                                                                                                  
                                                              -Xms3000m                                                                                                                                              
                                                              -Xmx7200m                                                                                                                                              
                                                              -XX:+HeapDumpOnOutOfMemoryError                                                                                                                        
                                                              -XX:HeapDumpPath=/app/amix                                                                                                                             
## java -jar 启动
 CLASS-PATH                                                   /amix-2.5.0.jar:/app/skywalking-agent/skywalking-agent.jar                                                                                             
 BOOT-CLASS-PATH                                              /usr/local/openjdk-8/jre/lib/resources.jar:/usr/local/openjdk-8/jre/lib/rt.jar:/usr/local/openjdk-8/jre/lib/sunrsasign.jar:/usr/local/openjdk-8/jre/li 
                                                              b/jsse.jar:/usr/local/openjdk-8/jre/lib/jce.jar:/usr/local/openjdk-8/jre/lib/charsets.jar:/usr/local/openjdk-8/jre/lib/jfr.jar:/usr/local/openjdk-8/jr 
                                                              e/classes                                                                                                                                              
 LIBRARY-PATH                                                 /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib                                                                                           
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 CLASS-LOADING                                                                                                                                                                                                       
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 LOADED-CLASS-COUNT                                           57068                                                                                                                                                  
 TOTAL-LOADED-CLASS-COUNT                                     60880                                                                                                                                                  
## 如果这个值很大,需要看看内存情况,是否因为内存不足导致被迫换出
 UNLOADED-CLASS-COUNT                                         3812                                                                                                                                                   
 IS-VERBOSE                                                   false                                                                                                                                                  
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 COMPILATION                                                                                                                                                                                                         
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 NAME                                                         HotSpot 64-Bit Tiered Compilers                                                                                                                        
 TOTAL-COMPILE-TIME                                           489158                                                                                                                                                 
 [time (ms)]                                                                                                                                                                                                         
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 GARBAGE-COLLECTORS                                                                                                                                                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## PS GC 年轻代
 PS Scavenge                                                  name : PS Scavenge                                                                                                                                     
 [count/time (ms)]                                            collectionCount : 1729                                                                                                                                 
                                                              collectionTime : 40492                                                                                                                                 
## PS GC 老年代
 PS MarkSweep                                                 name : PS MarkSweep                                                                                                                                    
 [count/time (ms)]                                            collectionCount : 25                                                                                                                                   
                                                              collectionTime : 30811                                                                                                                                 
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MEMORY-MANAGERS                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## 代码缓存区 
 CodeCacheManager                                             Code Cache                                                                                                                                             
## 元空间
 Metaspace Manager                                            Metaspace                                                                                                                                              
                                                              Compressed Class Space                                                                                                                                 
## 堆 年轻代
 PS Scavenge                                                  PS Eden Space                                                                                                                                          
                                                              PS Survivor Space                                                                                                                                      
## 堆 老年代
 PS MarkSweep                                                 PS Eden Space                                                                                                                                          
                                                              PS Survivor Space                                                                                                                                      
                                                              PS Old Gen                                                                                                                                             
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MEMORY                                                                                                                                                                                                              
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 ## 堆,可以看到为了应对特定情况浪费很明显
 HEAP-MEMORY-USAGE                                            init : 3145728000(2.9 GiB)                                                                                                                             
 [memory in bytes]                                            used : 669297048(638.3 MiB)                                                                                                                            
                                                              committed : 4256694272(4.0 GiB)                                                                                                                        
                                                              max : 6710886400(6.3 GiB)                                                                                                                              
## 堆外内存 = Code Cache + Metaspace
## 直接内存(Direct Memory)单独计算,JVM自身会占用一部分
## 堆外内存都可以使用对应的Max*Size配置最大值,一般不配置;通常直接内存都为0,
## 在WEB后端程序中,一般很少主动使用直接内存,主流的框架默认都不使用直接内存(如nacos等)
## 因此计算最大内存需求时考虑堆内存+代码缓存+元空间+线程栈和+直接内存
## 线程栈内存默认1M,一般WEB后台程序中预留100-300M
## 通常启动时堆空间都是不满的,堆外内存溢出不会突然显现(操作系统虽然给满了虚拟内存但实际上不会一次性给那么多物理内存)
## 但是随着使用峰值而突然超出阈值导致内存不足从而换入swp导致性能下降甚至被OS主动Kill,尤其时在容器中时要注意可能会OOMKilll,如下方容器OOM示例
## 因此操作系统可用的用户空间内存一般要大于堆内存空间+堆外内存预留空间
 NO-HEAP-MEMORY-USAGE                                         init : 2555904(2.4 MiB)                                                                                                                                
 [memory in bytes]                                            used : 534662568(509.9 MiB)                                                                                                                            
                                                              committed : 605052928(577.0 MiB)                                                                                                                       
                                                              max : -1(-1 B)                                                                                                                                         
## JDK1.8中都已经置为过时了,后续的JDK可能会直接删除,因此如果有用finalize最好优化掉
 PENDING-FINALIZE-COUNT                                       0                                                                                                                                                      
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 OPERATING-SYSTEM                                                                                                                                                                                                    
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 OS                                                           Linux                                                                                                                                                  
 ARCH                                                         amd64                                                                                                                                                  
 PROCESSORS-COUNT                                             3                                                                                                                                                      
 LOAD-AVERAGE                                                 0.51                                                                                                                                                   
 VERSION                                                      5.10.179-1.el7.x86_64                                                                                                                                  
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 THREAD                                                                                                                                                                                                              
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## 线程数,线程数过高也是不可忽视的,一方面栈内存开销会直接增加,另一方面活动的线程过多也会导致CPU竞争激烈 
 COUNT                                                        165                                                                                                                                                    
 DAEMON-COUNT                                                 88                                                                                                                                                     
 PEAK-COUNT                                                   181                                                                                                                                                    
 STARTED-COUNT                                                291044                                                                                                                                                 
## 死锁
 DEADLOCK-COUNT                                               0                                                                                                                                                      
                                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 FILE-DESCRIPTOR                                                                                                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## 文件描述符.OPEN数量过大也需要排查下原因
 MAX-FILE-DESCRIPTOR-COUNT                                    1048576                                                                                                                                                
 OPEN-FILE-DESCRIPTOR-COUNT                                   469                                                                                                                                                    
  # 某容器中因为堆外内存不够而OOM示例,设置容器内存时仅考虑了堆内存,因此启动过程中就直接导致OOMKill
  # k8s文档:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-memory-resource/
  # memory limit: 1010M
  # jvm heap limit: 1000M
  # 预留的内存过少,在峰值时就OOM了
  - containerID: docker://c40f84bb3169c377b57300a976bb2f10eaa9c927fe0637ad7382450936ed8844
    image: registry.xxx.com/xxx/xxx-uat2:2023.9.8-173241-release-UAT2-V3
    imageID: docker-pullable://registry.xxx.com/xxx/xxx-uat2@sha256:e53adbb497b0fc7bf851edcf6d78e4707bdf349228d00e5fd5110e4389351a65
    lastState:
      terminated:
        containerID: docker://22f800545462fad80aa6681ee4d302cb27a65b27f2d41dfe3b7347e3ff4e8aab
        exitCode: 137
        finishedAt: "2023-10-07T14:56:15Z"
        reason: OOMKilled
        startedAt: "2023-10-07T14:40:57Z"
    name: cbms-fund-uat2

dashboard 实时信息面板

文档:arthas.aliyun.com/doc/dashboa…

memory 查看内存信息

[arthas@14844]$ memory
## 内存类型 使用量 总量 最大限制量 使用率(使用量/总量)
Memory                                             used             total            max              usage
## 堆
heap                                               81M              162M             3886M            2.11%
## GC相关
g1_survivor_space                                  4M               6M               -1               72.05%
g1_eden_space                                      12M              66M              -1               18.18%
g1_old_gen                                         65M              90M              3886M            1.69%
## 堆外
nonheap                                            113M             115M             -1               97.69%
## 元空间
metaspace                                          80M              81M              -1               99.17%
## 编译后的类空间
compressed_class_space                             10M              11M              1024M            1.06%
## 代码缓存
codecache                                          22M              23M              48M              46.07%
## 内存映射量
mapped                                             0K               0K               -                0.00%
## 直接内存
direct                                             16M              16M              -                100.00%
## 内存映射量
mapped - 'non-volatile memory'                     0K               0K               -                0.00%

classloader 查看或使用类加载器

## 按类加载实例进行统计,主要为获取到类加载器实例的hash并在其他地方用-c参数指定该类加载器
[arthas@11288]$ classloader  -l
 name                                                           loadedCount  hash      parent
 BootstrapClassLoader                                           5108         null      null
 com.taobao.arthas.agent.ArthasClassloader@2fd43f45             1384         2fd43f45  jdk.internal.loader.ClassLoader
                                                                                       s$PlatformClassLoader@1dc4f3f3
 jdk.internal.loader.ClassLoaders$AppClassLoader@2b193f2d       10588        2b193f2d  jdk.internal.loader.ClassLoader
                                                                                       s$PlatformClassLoader@1dc4f3f3
 jdk.internal.loader.ClassLoaders$PlatformClassLoader@1dc4f3f3  216          1dc4f3f3  null
 sun.reflect.misc.MethodUtil@775d7713                           1            775d7713  jdk.internal.loader.ClassLoader
                                                                                       s$AppClassLoader@2b193f2d
Affect(row-cnt:5) cost in 6 ms.

## 统计 ClassLoader 实际使用 URL 和未使用的 URL
## 主要用于项目中观察哪些包没用,以及多个包冲突的时候实际加载的哪个
[arthas@11288]$ classloader --url-stat

## 通过类加载器名称指定类加载器查找类
[arthas@11288]$ classloader --classLoaderClass jdk.internal.loader.ClassLoaders$AppClassLoader -r java/lang/String.class
## 通过类加载器hash指定类加载器查找类
[arthas@11288]$ classloader -c 2b193f2d -r java/lang/String.class

jad 反编译

## 反编译指定类方法 jad --source-only 类名 方法名
[arthas@11288]$ jad --source-only java.lang.Object equals
        public boolean equals(Object obj) {
/*163*/     return this == obj;
        }

monitor 监控方法调用统计

文档:arthas.aliyun.com/doc/monitor…

格式:monitor 参数 类 方法 条件

## 10秒刷新一次监听PublicRestfulTpController#enumeration执行情况
[arthas@11288]$ monitor com.crykasset.yktpwx.controller.pub.PublicRestfulTpController enumeration  'params[0] =="TP_TYP E" ' -c 10
### curl -X GET "http://127.0.0.1:7091/tp/pubRf/api/enum?keys=TP_TYPE" -H "accept: application/json"

profiler 生成火焰图

文档:arthas.aliyun.com/doc/profile…

仅支持Linux或Mac,主要用于压测观察cpu或内存情况

stack 观察方法调用栈信息

文档:arthas.aliyun.com/doc/stack.h…

格式:stack 参数 类 方法 条件

## 观察当参数为TP_TYPE时PublicRestfulTpController#enumeration执行情况
[arthas@11288]$ stack com.crykasset.yktpwx.controller.pub.PublicRestfulTpController enumeration  'params[0] =="TP_TYPE" '
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 45 ms, listenerId: 2
ts=2023-10-10 12:33:26;thread_name=http-nio-7091-exec-2;id=3a;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@71c91121
    @com.crykasset.yktpwx.controller.pub.PublicRestfulTpController.enumeration()

trace 追踪方法执行堆栈

文档:arthas.aliyun.com/doc/trace.h…

格式:trace 参数 类 方法 条件

## 监听PublicRestfulTpController#enumeration执行堆栈
[arthas@11288]$ trace com.crykasset.yktpwx.controller.pub.PublicRestfulTpController enumeration  'params[0] =="TP_TYPE" '
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 87 ms, listenerId: 3
`---ts=2023-10-10 12:39:56;thread_name=http-nio-7091-exec-3;id=3b;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@71c91121
    `---[42.4559ms] com.crykasset.yktpwx.controller.pub.PublicRestfulTpController:enumeration()
        `---[99.75% 42.3489ms ] com.crykasset.yktpwx.service.comm.EnumsService:enumeration() #40

thread 观察线程堆栈

文档:arthas.aliyun.com/doc/thread.…

watch 观察指定函数执行

文档:arthas.aliyun.com/doc/watch.h…

格式:watch 类 方法 目标Array 条件 参数

其中类和方法都支持*(星号)匹配

匹配类时默认匹配子类,可以通过两种方式排除:

1。先执行命令options disable-sub-class true关闭子类匹配

2。watch时添加参数--exclude-class-pattern xxx类全称

3。全局参数文档:arthas.aliyun.com/doc/options…

常用方式示例:

//观察PublicRestfulTpController#enumeration方法执行后的结果,展示深度为3,过滤条件为第一个参数等于TP_TYPE且执行耗时大于30毫秒
watch com.crykasset.yktpwx.controller.pub.PublicRestfulTpController enumeration "{params, returnObj, throwExp}" 'params[0] =="TP_TYPE" and #cost>30' -f -x 4

//然后 curl -X GET "http://127.0.0.1:7091/tp/pubRf/api/enum?keys=TP_TYPE" -H "accept: application/json"

/*
## 方法=方法名全称 执行结果=正常退出
method=com.crykasset.yktpwx.controller.pub.PublicRestfulTpController.enumeration location=AtExit
## 执行时间; [耗时=毫秒] 结果=以观察表达式为顺序的List[参数列表值、返回值、异常值]
ts=2023-10-09 21:34:21; [cost=571.3545ms] result=@ArrayList[
## 参数列表
    @Object[][
        @String[TP_TYPE],
    ],
## 返回值,拉高深度为4正好可以看到具体的内容
    @HashMap[
        @String[TP_TYPE]:@ArrayList[
            @EnumVo[
                code=@String[ZS],
                name=@String[招商],
                value=null,
                summary=null,
            ],
            @EnumVo[
                code=@String[PM],
                name=@String[拍卖],
                value=null,
                summary=null,
            ],
        ],
    ],
## 正常退出没有异常
    null,
]
*/

tt 记录方法执行

命令语法:arthas.aliyun.com/doc/tt.html

格式:

观察:tt -t 其他参数(-n -m) 类 方法 OGNL条件表达式

检索调用记录:tt -l tt -s OGNL条件表达式

查看特定调用记录信息:tt -x 深度 -i 索引INDEX

重做特定调用记录:tt -i 索引 -p -x 深度 --replay-times 次数 --replay-interval 间隔毫秒默认1000

在特定调用记录执行表达式获取表达式结果:tt -w OGNL表达式 -x 深度 -i 索引

常用方式示例:

//观察PublicRestfulTpController#enumeration方法执行情况,记录条件为第一个参数等于TP_TYPE或TP_PM_STAGE,最大观察类1,最大观察次数3
tt -t -m 1 -n 3 com.crykasset.yktpwx.controller.pub.PublicRestfulTpController enumeration 'params[0]=="TP_TYPE" or params[0]=="TP_PM_STAGE"'

//然后
//curl -X GET "http://127.0.0.1:7091/tp/pubRf/api/enum?keys=TP_TYPE" -H "accept: application/json"
//curl -X GET "http://127.0.0.1:7091/tp/pubRf/api/enum?keys=TP_PM_STAGE" -H "accept: application/json"

//查询全部记录
tt -l
//筛选参数是TP_TYPE的记录
tt -s 'params[0]=="TP_TYPE"'
//查看索引为1000的记录,查看深度为4
 tt -x 4 -i 1000
//重做索引为1000的记录并观察结果,查看深度为4
tt -p -i 1000 -x 4
//在索引1000的记录执行表达式,获得返回值map的key为TP_TYPE的值,查看深度为2
tt -w 'returnObj["TP_TYPE"]' -x 2 -i 1000

ognl 执行任意OGNL表达式

命令语法:arthas.aliyun.com/doc/ognl.ht…

格式:ognl 表达式 -x 深度 -c ClassLoader的HashCode --classLoaderClass ClassLoader的全称

常用方式示例:

//获取Spring Bean:publicRestfulTpController并执行方法enumeration
ognl -x 3 '#b=@com.crykasset.yktpwx.YkTpWxApplication@ctx.getBean("publicRestfulTpController"),#b.enumeration("TP_TYPE")'

heapdump 类似 jmap 命令的 heap dump 功能

用法:heapdump 文件路径名称如/tmp/dump.hprof

和jmap一样--live参数控制仅导出活动对象

retransform 热更新class

一般用法:retransform -c ClassLoader的HashCode class文件路径名称

指南:arthas.aliyun.com/doc/retrans…

## 热更新指定类,如果使用了自定义的类加载器,则建议指定和原类加载器相同的类加载器
## 1. 先查原类的类加载器
## JDK9及以上需要启动时添加3个参数:
## 文档:https://dev.java/learn/modules/add-exports-opens/
## --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED
[arthas@15972]$ ognl '@com.crykasset.yktpwx.controller.pub.PublicRestfulTpController@class.getClassLoader().hashCode()' 
@Integer[723074861]
## 2. 执行热更新
[arthas@11288]$ retransform  D:/Codes/cbms-yk/yk-tp-app/target/classes/com/crykasset/yktpwx/controller/pub/PublicRestfulTpController.class
retransform success, size: 1, classes:
com.crykasset.yktpwx.controller.pub.PublicRestfulTpController
### curl -X GET "http://127.0.0.1:7091/tp/pubRf/api/enum?keys=TP_TYPE" -H "accept: application/json"