官方文档 Arthas(阿尔萨斯)是阿里巴巴开源的一款Java诊断工具,用于实时检测、诊断Java应用程序的性能问题。它是一个命令行工具,提供了丰富的功能,包括查看类加载信息、方法执行耗时、线程堆栈、内存分析等。Arthas 的设计目标是在生产环境中实时诊断和解决Java应用程序的问题。 以下是 Arthas 的一些主要特点和功能:
实时性: Arthas 可以在运行中的 Java 进程中实时进行诊断,无需重新启动应用。
丰富的命令: 提供了众多的命令,涵盖了类加载、方法执行、线程、内存、GC 等多个方面。
动态追踪: 支持实时动态追踪方法调用、线程堆栈等信息,方便定位问题。
内存分析: 提供了 Heap Dump、Histogram、Classloader Stats 等命令,帮助进行内存分析。
多种环境支持: 支持 Linux、Mac 和 Windows 操作系统,支持 HotSpot 和 OpenJ9 JVM。
在线帮助: 提供了丰富的在线帮助,用户可以通过 help 命令查看每个命令的详细说明。
主要有以下几大组件:
arthas-core.jar 是服务器端的启动入口类,调用 VirtualMachine#attach 到目标进程,并加载 arthas-agent.jar 作为 agent 包。
arthas-agent.jar 既可以使用 premain 方式(在目标进程启动之前,通过-agent参数静态指定),也可以通过 agentmain 方式(在进程启动之后attach上去)。arthas-agent会使用自定义的classloader(ArthasClassLoader)加载arthas-core.jar里面的Configure类以及ArthasBootstrap。 同时程序运行的时候会使用arthas-spy.jar。
arthas-spy.jar 里面只包含Spy类,目的是为了将Spy类使用BootstrapClassLoader来加载,从而使目标进程的java应用可以访问Spy类。通过ASM修改字节码,可以将Spy类的方法ON_BEFORE_METHOD, ON_RETURN_METHOD等编织到目标类里面。
arthas-client.jar 是客户端程序,用来连接arthas-core.jar启动的服务端代码,使用telnet方式。一般由arthas-boot.jar和as.sh来负责启动。
text# 下载 curl -O https://arthas.aliyun.com/arthas-boot.jar # 启动服务 java -jar arthas-boot.jar # 查看帮助 help
#对文件进行 base64 编码 base64 /tmp/test.txt #对文件进行 base64 编码并把结果保存到文件里 base64 --input /tmp/test.txt --output /tmp/result.txt #用 base64 解码文件 base64 -d /tmp/result.txt #用 base64 解码文件并保存结果到文件里 base64 -d /tmp/result.txt --output /tmp/bbb.txt
cat /tmp/a.txt
cls
echo 'hello'
help
#查看最近执行的3条指令 $ history 3 #清空指令 history -c
keymap
pwd
#等同于exit、logout、q三个指令。 quit
#还原指定类 reset Test #还原所有类 reset
session
#关闭 Arthas 服务器之前,会重置掉所有做过的增强类。但是用 redefine 重加载的类内容不会被重置。 stop
sysprop | tee -a /path/to/logfile | grep java
version
数据说明: ID:Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应 NAME:线程名 GROUP:线程组名 PRIORITY:线程优先级, 1~10之间的数字,越大表示优先级越高 STATE:线程的状态 CPU%:线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。 TIME:线程运行总时间,数据格式为分:秒 INTERRUPTED:线程当前的中断位状态 DAEMON:是否是daemon线程
GC区域说明: gc.ps_scavenge.count:从应用程序启动到当前采样时间年轻代gc次数
gc.ps_scavenge.time(ms):从应用程序启动到当前采样时间年轻代gc所用的总时间(毫秒)
gc.ps_marksweep.count:从应用程序启动到当前采样时间老年代gc次数
gc.ps_marksweep.time(ms):从应用程序启动到当前采样时间老年代gc所用的总时间(毫秒)
Memory 区域主要参数说明:
heap:堆内存使用情况(ps_eden_space+ps_survivor_space+ps_old_gen)
ps_eden_space:伊甸园区内存使用情况
ps_survivor_space:幸存区内存使用情况
ps_old_gen :老年代内存使用情况
nonheap:非堆内存使用情况
输入 q 或者 Ctrl+C 可以退出dashboard命令
#推荐直接使用ognl命令,更加灵活。 getstatic class_name field_name
heapdump arthas-output/dump.hprof
jvm
COUNT: JVM 当前活跃的线程数
DAEMON-COUNT: JVM 当前活跃的守护线程数
PEAK-COUNT: 从 JVM 启动开始曾经活着的最大线程数
STARTED-COUNT: 从 JVM 启动开始总共启动过的线程次数
DEADLOCK-COUNT: JVM 当前死锁的线程数
logger
列出所有 Mbean 的名称: mbean 查看 Mbean 的元信息: mbean -m java.lang:type=Threading 查看 mbean 属性信息: mbean java.lang:type=Threading mbean 的 name 支持通配符匹配: mbean java.lang:type=Th*
memory
调用静态函数: ognl '@java.lang.System@out.println("hello")' 获取静态类的静态字段: ognl '@demo.MathGame@random'
perfcounter
sysenv
查看所有 sysprop 查看单个 sysprop java.version 修改单个 $ sysprop user.country user.country=US $ sysprop user.country CN
参数说明:
数字:
线程id
[n:]:指定最忙的前N个线程并打印堆栈
[b]:找出当前阻塞其他线程的线程
[i ] :指定cpu占比统计的采样间隔,单位为毫秒
Arthas支持管道,可以用 thread 1 | grep 'main(' 查找到main class。
textthread 1 | grep 'main(' thread # 显示所有线程的信息 thread 1 # 显示1号线程的运行堆栈 thread -b # 查看阻塞的线程信息 thread -n 3 # 查看最忙的3个线程,并打印堆栈 thread -i 1000 -n 3 # 指定采样时间间隔,每过1000毫秒采样,显示最占时间的3个线程
查看处于等待状态的线程(WAITING、BLOCKED) thread --state WAITING
查看所有 vmoption 查看指定的 option vmoption PrintGC 更新指定的 option vmoption PrintGC true
获取对象 vmtool --action getInstances --className java.lang.String --limit 10 指定 classloader name vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframe 强制 GC vmtool --action forceGc
classloader
dump -d /tmp/output java.lang.String
jad java.lang.String jad demo.MathGame -d /tmp/jad/dump
mc /tmp/Test.java
推荐使用 retransform 命令 redefine /tmp/Test.class
retransform /tmp/Test.class
模糊搜索 sc demo.* 打印类的详细信息 sc -d demo.MathGame 打印出类的 Field 信息 sc -d -f demo.MathGame
# 输出这个类的所有方法 sm java.lang.String ## 输出方法的信息 sm -d java.lang.String toString
注意
请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 stop 或将增强过的类执行 reset 命令。
monitor -c 5 demo.MathGame primeFactors
stack demo.MathGame primeFactors
trace demo.MathGame run
记录调用 tt -t demo.MathGame primeFactors
可以实现观察方法的入参出参`
# watch 类地址 方法名 '{params,returnObj}' -x 2 watch com.lhw.product.client.StairLiftClient getplatformStatus '{params,returnObj}' -x 2
如果请求或者返回值多层对象嵌套 可以改成3
watch 类地址 方法名 '{params,returnObj}' -x 3
需要进入应用内部后运行arthas
sudo docker exec -it 应用名或者应用的id bash cd opt # 进入opt后创建arthas文件夹 mkdir arthas cd arthas # 下载arthas-boot.jar curl -O https://arthas.aliyun.com/arthas-boot.jar #退出应用内部空间 exit # 启动arthas docker exec -it 应用名或者应用的id /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar"
docker exec -it 应用名或者应用的id /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"
编译docker应用时就将arthas需要的相关文件放入/opt/arthas/下
dockerFile文件:
FROM openjdk:8-jdk-alpine # copy arthas COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas
将hengyunabc/arthas
镜像的/opt/arthas下的文件拷贝到应用镜像的/opt/arthas目录中启动
docker exec -it 应用名或者应用的id /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar"
本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!