Arthas 是阿里开源的Java诊断工具。安装在系统所在服务器,有着强大的能力,是一个开发运维神器。主要功能:
- 在线热替换代码/代码增强
- 全局视角的性能分析
- 查看方法执行情况,帮助跟踪偶现的bug
官方网站资料 https://arthas.aliyun.com/doc/
容器中使用
根据官方手册,在容器中下载curl下载该工具并简单使用
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
- 执行该程序的用户需要和目标进程具有相同的权限。比如以admin用户来执行:sudo su admin && java -jar arthas-boot.jar 或 sudo -u admin -EH java -jar arthas-boot.jar。
- 如果 attach 不上目标进程,可以查看~/logs/arthas/ 目录下的日志。
- 如果下载速度比较慢,可以使用 aliyun 的镜像:java -jar arthas-boot.jar --repo-mirror aliyun --use-http
- java -jar arthas-boot.jar -h 打印更多参数信息
常用命令
详细见官方手册命令
version:查看当前Arthas版本
help:arthas命令行帮助
dashboard:系统监控台信息
thread :查看线程信息
查看所有线程信息
thread
查看线程ID 2的栈:
thread 2
查看CPU使用率top n线程的栈
thread -n 3
查看5秒内的CPU使用率top n线程栈
thread -n 3 -i 5000
查找线程是否有阻塞
thread -b
#反编译想要的类,保存为文本文件
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
#命令则是查找类的具体函数
sm -d java.math.RoundingMode
#sc查找jvm加再的累
sc -d *UserController | grepclassLoaderHash
#方法监控
monitor -c 5 class method
#如果是列表,则会过滤列表中长度大于10的字符串
watch class method "{params,returnObj,throwExp}" "params[0].length() > 10" -x 1
#按条件过滤后展示指定属性
watch class method "{params[0].{? #this.name.length() > 5}.{age}}" -n 1 -x 1
#找到第一个符合条件的数据,用^
watch class method "{params[0].{^ #this.name.length() > 5}.{age}}" -n 1 -x 1
#找到最后一个符合条件的数据,用$
watch class method "{params[0].{$ #this.name.length() > 5}.{age}}" -n 1 -x 1
#追踪方法的内部调用
trace class method -n 5 --skipJDKMethod false
#过滤大于200ms的调用链,只输出一次
trace class method '#cost>200' -n 1
配置dockerfile
在构建镜像时候,可以把arthus注入到dockerfile中,方便容器排障
#docker file参考配置
FROM myhuawei.com/devops/builder-java-openjdk17:openjdk-maven-v1
WORKDIR /app
COPY target/gateway-0.0.1-SNAPSHOT.jar .
COPY start.sh .
RUN chmod 777 /app/start.sh
RUN chmod +x /app/start.sh
EXPOSE 41579
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 设置系统时间为24小时制
RUN apt-get update && apt-get install -y locales
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV TZ=Asia/Shanghai
#CMD ["java","-Xms4096m","-Xmx4096m","-Dfile.encoding=UTF8","-Dsun.jnu.encoding=UTF8","-jar","/app/gateway-0.0.1-SNAPSHOT.jar"]
ENTRYPOINT ["/app/start.sh"]
#安装arthus工具
RUN curl -O https://arthas.aliyun.com/arthas-boot.jar
排障举例
排查内存占用大的地方
行memory命令以获取当前Java虚拟机(JVM)的整体内存使用状态,包括堆内存、非堆内存以及各细分区域的使用详情。这一步对于识别内存是否泄漏及大致位置至关重要。
$ memory
分析关键词解释
- 观察heap区域,特别是g1_old_gen的增长情况,因为长期存活的对象通常在此积累。
- 注意nonheap区域,特别是metaspace的增长,过大的类元数据可能导致问题。
- 检查是否有特定的codeheap区域异常增长,这可能意味着即时编译的代码占用过多内存。
定位内存泄漏
- 连续监控:多次执行memory命令并记录结果,关注任何持续增长的内存区域。
- 堆转储分析:使用heapdump命令生成堆的快照,随后利用如Eclipse MAT等工具深入分析增长的对象类型和引用链路。
[arthas@58205]$ heapdump arthas-output/dump.hprof
解释
通过对比不同时间点的memory命令输出,可以发现内存泄漏的趋势。而heapdump生成的堆转储文件能够提供泄露对象的详细信息,包括它们的数量、大小及引用关系,这对于定位具体泄漏源非常关键。
排查HTTP请求返回401
通常是被权限管理的Filter拦截了,那么到底是哪个Filter处理了这个请求,返回了401?
trace javax.servlet.Filter *
可以在调用树的最深层,找到AdminFilterConfig$AdminFilter返回了401
分析线程卡住
thread -b
此命令会列出当前阻塞其他线程的线程信息,包括线程ID、状态以及它持有的锁。例如,输出可能会显示某个线程处于TIMED_WAITING状态,并指出该线程持有一个锁,同时阻塞了其他线程。
关注锁定对象:注意输出中被- locked标记的行,这表示该线程持有的锁。如果该锁导致了其他线程的阻塞,这里会有明确提示。
查看调用栈:调用栈信息可以帮助理解该线程在阻塞前正在执行的操作,这对于诊断问题至关重要。