Java线上监控诊断产品Arthas(续集)
- 前言
 - 1.auth指令
 - 2.monitor指令
 - 解读
 
- 3.classloader指令
 - 场景
 
- 4.dump指令
 - 场景
 
- 5.getstatic指令
 - 场景
 
- 6.heapdump指令
 - 场景
 
- 7.profiler指令
 - 场景
 
- 8.sc指令
 - 场景
 
- 9.trace指令
 - 场景
 
前言
在去年,我发表了一片文章,Java线上监控诊断产品Arthas,今年又重新回顾了一下这门技术,发现了以前忽略了很多技术点,这篇文章用来作补充,并且思考了一下这些技术点可以用来哪些场景。
1.auth指令
在 attach 时,可以在命令行指定密码。比如:
java -jar arthas-boot.jar --password admin
 
- 可以通过 --username 选项来指定用户,默认值是arthas。
 - 也可以在 arthas.properties 里中配置 username/password。命令行的优先级大于配置文件。
 - 如果只配置username,没有配置password,则会生成随机密码,打印在~/logs/arthas/arthas.log中
 
本地连接不鉴权
 为了方便本地开发和调试,Arthas 默认允许本地连接不进行鉴权。,在arthas.properties文件里有配置:
arthas.localConnectionNonAuth=true
 
这样,即使设置了密码,本地连接也无需进行认证。
 telnet链接鉴权
 远程连接后,需要输入auth指令,输入正确密码,这样才能执行arthas的命令。
[arthas@37430]$ auth admin
Authentication result: true
 
不然会提示:
Error! command not permitted, try to use 'auth' command to authenticates.
 
2.monitor指令
案例一:最简单的应用,-c参数:统计周期,默认为120秒,我这5秒一次
monitor -c 5 com.example.demo.controller.ArthasController test
 
输入之后界面这样,没有任何输出:
[arthas@2719]$ monitor -c 5 com.example.demo.controller.ArthasController test
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 220 ms, listenerId: 2
 
然后我在浏览器疯狂请求这个接口几次,看看输出:
 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:40                  com.example.demo.controller.ArthasController           test                                                    1                 1                  0                 5.53               0.00%            
 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:45                  com.example.demo.controller.ArthasController           test                                                    6                 6                  0                 1.91               0.00%            
 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:47                  com.example.demo.controller.ArthasController           test                                                    9                 9                  0                 0.13               0.00%            
 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:55                  com.example.demo.controller.ArthasController           test                                                    0                 0                  0                 0.00               0.00%        
 
案例二:
 此指令还支持条件匹配式,我这里举个最简单的例子:
 “params[0]<=2”,表示接口的第一个参数必须<=2
monitor -c 5 com.example.demo.controller.ArthasController test "params[0]<=2"
 
经过测试,我参数传2的时候,可以检测到,当我参数num传3的时候,就检测不到:
 接口:http://172.16.72.132:8081/arthast/inputNum?num=3
timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:59:31                  com.example.demo.controller.ArthasController           test                                                    1                 1                  0                 0.21               0.00%            
 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:59:41                  com.example.demo.controller.ArthasController           test                                                    0                 0                  0                 0.00               0.00%          
 
解读
1.由上面的场景可以看出来,这个指令可以监控一个方法,在一定时间(-c控制)里被请求了多少次,可以用来压测、或者是热点接口监控,可以显示成功和失败率,并且可以显示平均 RT。
 2.指令的条件匹配式,还可以帮助我们筛选想要的请求进来统计。
3.classloader指令
查看 classloader 的继承树,urls,类加载信息
-  
classloader -l 按类加载实例进行统计
[arthas@2719]$ classloader -l name loadedCount hash parent BootstrapClassLoader 4393 null null com.taobao.arthas.agent.ArthasClassloader@dfd4a07 1702 dfd4a07 jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665 jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd 47 5c29bfd jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665 jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665 115 71423665 null org.springframework.boot.loader.LaunchedURLClassLoader@9629756 10082 9629756 jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd Affect(row-cnt:5) cost in 11 ms. -  
classloader -t 打印所有 ClassLoader 的继承树
[arthas@2719]$ classloader -t +-BootstrapClassLoader +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665 +-com.taobao.arthas.agent.ArthasClassloader@dfd4a07 +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756 Affect(row-cnt:5) cost in 11 ms. 
注意:上面打印出来的信息,尾部有@9629756 这种编号,这是类加载器的HashCode值,后面我们如果要指定类加载器,参数跟的就是这一串HashCode。
- classloader -c 显示类加载器位置,配合load参数,可以指定用某个类加载器去加载某个类。
 
[arthas@2719]$ classloader -c 9629756 --load com.example.demo.controller.FileController
load class success.
 class-info        com.example.demo.controller.FileController                                                                                                                                                                                   
 code-source       file:/data/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/                                                                                                                                                                       
 name              com.example.demo.controller.FileController                                                                                                                                                                                   
 isInterface       false                                                                                                                                                                                                                        
 isAnnotation      false                                                                                                                                                                                                                        
 isEnum            false                                                                                                                                                                                                                        
 isAnonymousClass  false                                                                                                                                                                                                                        
 isArray           false                                                                                                                                                                                                                        
 isLocalClass      false                                                                                                                                                                                                                        
 isMemberClass     false                                                                                                                                                                                                                        
 isPrimitive       false                                                                                                                                                                                                                        
 isSynthetic       false                                                                                                                                                                                                                        
 simple-name       FileController                                                                                                                                                                                                               
 modifier          public                                                                                                                                                                                                                       
 annotation        org.springframework.stereotype.Controller,org.springframework.web.bind.annotation.RequestMapping                                                                                                                             
 interfaces                                                                                                                                                                                                                                     
 super-class       +-java.lang.Object                                                                                                                                                                                                           
 class-loader      +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756                                                                                                                                                             
                     +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                  
                       +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                          
 classLoaderHash   9629756  
 
场景
可以让指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。并且还可以指定类类的加载器,对于ResourceNotFoundException比较有用。
4.dump指令
dump 已加载类的 bytecode 到特定目录
场景
将 JVM 中实际运行的 class 的 byte code dump 到指定目录,适用场景批量下载指定包目录的 class 字节码;如需反编译单一类、实时查看类信息,可参考 jad。
-  
dump -d /xx dump到指定目录
[arthas@2719]$ dump -d /data com.example.demo.controller.UserInfoController HASHCODE CLASSLOADER LOCATION 9629756 +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756 /data/org.springframework.boot.loader.LaunchedURLClassLoader-9629756/com/example/demo/controller/UserInfoController.class +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665 Affect(row-cnt:1) cost in 202 ms.我们看看/data下面的目录文件:
[root@localhost data]# ll /data/ 总用量 100884 -rw-r--r--. 1 root root 141899 8月 2 23:45 arthas-boot.jar drwxr-xr-x. 2 root root 24 8月 4 01:46 arthas-output -rw-r--r--. 1 root root 99038636 8月 26 14:39 demo-0.0.1-SNAPSHOT.jar -rw-r--r--. 1 root root 179 8月 2 23:14 Dockerfile drwxr-xr-x. 2 root root 227 8月 26 11:04 logs -rw-r--r--. 1 root root 4120 8月 3 00:34 math-game.jar -rw-------. 1 root root 4097224 8月 26 14:59 nohup.out drwxr-xr-x. 3 root root 17 8月 26 15:50 org.springframework.boot.loader.LaunchedURLClassLoader-9629756 -rw-r--r--. 1 root root 598 8月 4 03:04 Test.class -rw-r--r--. 1 root root 446 8月 23 16:17 Test.javaorg.springframework.boot.loader.LaunchedURLClassLoader-9629756,这个文件就是我们刚刚dump出来的目录,我们进入目录一直点下去,就能看到最终的class文件:
[root@localhost controller]# ll 总用量 4 -rw-r--r--. 1 root root 2010 8月 26 15:50 UserInfoController.class -  
dump --classLoaderClass sun.misc.Launcher$AppClassLoader UserInfoController
用–classLoaderClass参数+ ClassLoader 的类名来指定类加载器加载,这里ClassLoader 实例必须唯一。classLoaderClass 在 java 8 是 sun.misc.Launcher$AppClassLoader,而 java 11 的 classloader 是 jdk.internal.loader.ClassLoaders$AppClassLoader 
5.getstatic指令
场景
想要知道某个类中的某个static修饰的字段的值是多少
 示例:
 我目前ArthasController 中的sum字段的值类型为Integer,值为6
[arthas@3126]$ getstatic com.example.demo.controller.ArthasController sum
field: sum
@Integer[6]
Affect(row-cnt:1) cost in 14 ms.
 
6.heapdump指令
场景
导出当前java的堆栈信息。
 示例:
[arthas@3126]$ heapdump /data/testDump.hprof
Dumping heap to /data/testDump.hprof ...
Heap dump file created
 
cd到/data目录后,就可以看到了:
-rw-------. 1 root root 76268636 8月  26 16:32 testDump.hprof
 
PS:这里的/data目录(本文几乎所有目录),是虚拟机的目录,不是arthas的目录,我们虽然attach上了arthas,控制台变了,但是我们还是可以访问宿主机的目录。默认路径是你arthas-boot.jar文件的目录
7.profiler指令
场景
生成火焰图
 示例:
 1.开始采样
[arthas@3126]$ profiler start
Profiling started
 
2.停止,会自动保存
[arthas@3126]$ profiler stop
OK
profiler output file: /data/arthas-output/20240826-170650.html
 
3.查看
 官方说的是用 http://localhost:3658/arthas-output/就能查看,但是我物理机去访问这个地址,ip和端口都没问题,但是就是访问不起,不知道啥情况, 最后只有将文件复制到Windows,然后用浏览器查看。
 最后结果就长这样,目前还不知道这个图怎么看,后面学习了再补充上。
 
8.sc指令
场景
查看 JVM 已加载的类信息
 可选参数-d,就是detail
[arthas@3126]$ sc -d com.example.demo.controller.UserInfoController 
 class-info        com.example.demo.controller.UserInfoController                                                                                                                                                                               
 code-source       file:/data/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/                                                                                                                                                                       
 name              com.example.demo.controller.UserInfoController                                                                                                                                                                               
 isInterface       false                                                                                                                                                                                                                        
 isAnnotation      false                                                                                                                                                                                                                        
 isEnum            false                                                                                                                                                                                                                        
 isAnonymousClass  false                                                                                                                                                                                                                        
 isArray           false                                                                                                                                                                                                                        
 isLocalClass      false                                                                                                                                                                                                                        
 isMemberClass     false                                                                                                                                                                                                                        
 isPrimitive       false                                                                                                                                                                                                                        
 isSynthetic       false                                                                                                                                                                                                                        
 simple-name       UserInfoController                                                                                                                                                                                                           
 modifier          public                                                                                                                                                                                                                       
 annotation        org.springframework.web.bind.annotation.RestController,org.springframework.web.bind.annotation.RequestMapping                                                                                                                
 interfaces                                                                                                                                                                                                                                     
 super-class       +-java.lang.Object                                                                                                                                                                                                           
 class-loader      +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756                                                                                                                                                             
                     +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                  
                       +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                          
 classLoaderHash   9629756                                                                                                                                                                                                                      
Affect(row-cnt:1) cost in 110 ms.
 
可选参数-f,需要配合-d一起使用,显示字段信息。
9.trace指令
场景
输出方法内部调用路径,从上往下层级调用输出,并输出方法路径上的每个节点上耗时
[arthas@3126]$ trace com.example.demo.controller.UserInfoController fileUpload
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 1030 ms, listenerId: 1
`---ts=2024-08-26 18:03:41;thread_name=http-nio-8081-exec-8;id=30;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@2ca6546f
    `---[75.03077ms] com.example.demo.controller.UserInfoController:fileUpload()
        +---[98.91% 74.209617ms ] com.example.demo.service.UserInfoService:list() #36
        `---[0.11% 0.084421ms ] com.example.demo.vo.ResultMsg:success() #37
 
这个接口的list方法耗时74.209617ms,占比98.91%,而ResultMsg:success()方法耗时0.084421ms,占比0.11%
以上就是对第一篇Java线上监控诊断产品Arthas内容的补充,如果后续有新的体会,出个3.0版本也说不一定,或者在本文继续补充。



















