百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

阿里巴巴开源的Java诊断工具Arthas最佳实践

csdh11 2025-03-03 18:11 31 浏览

1 概述

1.1 什么是Arthas

Arthas是Alibaba开源的Java诊断工具,深受开发者喜爱。

官网:
https://arthas.aliyun.com/zh-cn/

1.2 使用场景

1 这个类是从哪个jar包加载的?为什么会报各种类相关的Exception?

2 我改的代码为什么没有执行到?难道是我没commit?分支搞错了?

3 遇到问题无法在线上debug,难道只能通过加日志再重新发布吗?

4 线上遇到某个用户的数据处理有问题,但线上同样无法debug,线下无法重现!

5 是否有一个全局视角来查看系统的运行状况?

6 有什么办法可以监控到JVM的实时运行状态?

7 怎么快速定位应用的热点,生成火焰图?

1.3 运行环境要求

Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的Tab自动补全功能,进一步方便进行问题的定位和诊断。

2 安装与卸载

2.1 安装

命令

curl -O https://arthas.aliyun.com/arthas-boot.jar
# 必须要有个Java进程在执行
java -jar arthas-boot.jar
# 退出
exit

Arthas home:

/Users/liangyafei/.arthas/lib/3.6.0/arthas

Log home:

/Users/liangyafei/logs

2.2 卸载

因为这个Arthas是绿色软件,删除了安装目录和日志目录就可以了,即需要删除 .arthas 和logs这两个文件夹即可。

rm -rf /Users/liangyafei/.arthas
rm -rf /Users/liangyafei/logs

3 atach一个进程

3.1 一个案例

# 第一个窗口
cd /Users/liangyafei/.arthas/lib/3.6.0/arthas
java -jar math-game.jar

3.2 粘附进程

#第二个窗口
cd /Users/liangyafei/software/arthas
java -jar arthas-boot.jar
# 如果报错端口号被占用,则使用下面的命令
java -jar arthas-boot.jar --telnet-port 9998 --http-port -1
# Linux命令查看被占用的端口号
netstat -tnlp

3.3 浏览器连接Arthas

http://localhost:3658/

4 基础命令

4.1 help

查看命令帮助信息,可以查看当前arthas版本支持的指令,或者查看具体指令的使用说明。

4.2 cat

打印文件内容,和linux里的cat命令类似。

4.3 grep

查找命令,类似传统的grep命令。

4.4 pwd

返回当前的工作目录,和linux命令类似

4.5 cls

清空当前屏幕区域。

4.6 session

查看当前会话的信息

4.7 reset

重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类

4.8 version

输出当前目标 Java 进程所加载的 Arthas 版本号

4.9 quit

退出当前 Arthas 客户端,其他 Arthas 客户端不受影响

4.10 stop

关闭 Arthas 服务端,所有 Arthas 客户端全部退出

4.11 keymap

# 回到一行的开始
Ctrl+a
# 回到一行的结束
Ctrl+e

5 JVM相关

5.1 dashboard

作用:显示当前系统的实时数据面板,按q或者ctrl+c退出。

# 使用示例
dashboard

运行的所有的线程

ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
NAME: 线程名
GROUP: 线程组名
PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
STATE: 线程的状态
CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为秒
TIME: 线程运行总CPU时间,数据格式为分:秒
INTERRUPTED: 线程当前的中断位状态
DAEMON: 是否是daemon线程

内存使用情况

分为堆和非堆
堆:ps_eden_space、ps_survivor_space、ps_old_gen
非堆:code_cache、metaspace

JVM运行时状态

5.2 thread

作用:查看当前JVM的线程堆栈信息


参数名称

参数说明

数字

线程Id

[n:]

指定最忙的前N个线程并打印堆栈。

[b]

找出当前阻塞其他线程的线程。

[i ]

指定CPU占比统计的采样间隔,单位毫秒。

# 使用示例
# 1 显示线程1
thread 1
# 2 展示当前最忙的前3个线程并打印堆栈
thread -n 3
# 3 查看死锁
thread -b
# 4 每隔展示当前最忙的前3个线程并打印堆栈
thread -i 1000 -n 3
# 5 查看所有运行状态中的线程
thread --state RUNNABLE

5.3 jvm

作用:查看当前JVM信息。

# 使用示例
jvm
THREAD相关
COUNT: JVM当前活跃的线程数
DAEMON-COUNT: JVM当前活跃的守护线程数
PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
DEADLOCK-COUNT: JVM当前死锁的线程数

文件描述符相关
MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数

5.4 sysprop

作用:查看和修改当前JVM的系统属性(System Property)

# 使用示例
sysprop
# 1 查看Java home路径
sysprop java.home
# 2 查看国家
sysprop user.country
# 3 设置国家
sysprop user.country US

5.5 sysenv

作用:查看当前JVM的环境属性(System Environment Variables)

# 使用示例
sysenv
# 1 查看Java home路径
sysenv JAVA_HOME

5.6 vmoption

作用:查看,更新VM诊断相关的参数

# 使用示例
vmoption
# 1 查看PrintGCDetails
vmoption PrintGCDetails
# 2 设置PrintGCDetails
vmoption PrintGCDetails true

5.7 getstatic

作用:可以方便地查看类的静态属性。使用方法为getstatic class_name field_name,推荐使用ognl替换getstatic。

# 使用示例
getstatic demo.MathGame random

5.8 ognl

作用:执行ognl表达式,从3.0.5版本新增的功能。

# 使用示例
# 1 调用静态函数,后面的null为返回值
ognl '@java.lang.System@out.println("hello")'
null
# 2 获取静态类的静态字段
ognl '@demo.MathGame@random'
# 3 执行多行表达式,赋值给临时变量,返回一个List
ognl '#value1=@System@getProperty("java.home"),#value2=@System@getProperty("java.runtime.name"),{#value1,#value2}'
#返回值为
@ArrayList[
@String[/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre],
    @String[Java(TM) SE Runtime Environment],
]

6 class和classloader相关

6.1 sc

Search Class,搜索类

# 使用示例
# 1 搜索demo.MathGame
sc demo.MathGame
# 查看demo.MathGame详细信息
sc demo.MathGame -d
# 查看demo.MathGame详细信息,包括字段field
sc demo.MathGame -df
# 2 模糊搜索匹配
sc demo.*
# 3 搜索类默认会有子类,移除子类开关
options disable-sub-class true
# 再次测试
sc demo.Parent

6.2 sm

Search Method,搜索方法

# 使用示例
# 1 显示String类加载方法
sm java.lang.String
# 查看更加详细的信息
sm demo.MathGame -d

6.3 jad

作用:把字节码文件反编译成源代码

# 使用示例
jad demo.MathGame
# 不显示ClassLoader和Location
jad --source-only demo.MathGame
# 2 只反编译其中的一个方法
jad java.lang.String trim

6.4 mc

Memory Compiler/内存编译器,作用:在内存中把源代码编译成字节码文件。

# 使用示例
# 1 编译Hello.java
mc /root/Hello.java
# 生成的文件在:/Users/liangyafei/.arthas/lib/3.6.0/arthas路径下
# 2 指定文件夹
mc /root/Hello.java -d /root

6.5 redefine

作用:不允许新增field和method,正在跑的函数,没有退出不能生效,比较死循环里的代码。

# 1 使用jad反编译demo.MathGame输出到/Users/liangyafei/.arthas/lib/3.6.0/arthas/MathGame.java
jad --source-only demo.MathGame > /root/MathGame.javajad --source-only demo.MathGame > /Users/liangyafei/.arthas/lib/3.6.0/arthas/MathGame.java
# 2 按上面的代码编辑完毕以后,使用mc内存中对新的代码编译
mc /Users/liangyafei/.arthas/lib/3.6.0/arthas/MathGame.java -d /Users/liangyafei/.arthas/lib/3.6.0/arthas/
# 3 使用redefine命令加载新的字节码
/Users/liangyafei/.arthas/lib/3.6.0/arthas/demo/MathGame.class

6.6 dump

作用:将已经加载的类的字节码文件保存到特定目录:~/logs/arthas/classdump

# 使用示例
# 1 把String类的字节码保存到~/logs/arthas/classdump目录下
dump java.lang.String
# 输出:/Users/liangyafei/logs/arthas/classdump/java/lang/String.class
# 2 把demo包下所有的类的字节码文件保存到~/logs/arthas/classdump目录下
dump demo.*

6.7 classloader

作用:

1 将JVM中所有的classloader的信息统计出来,并可以展示继承树,urls等。

2 可以让指定的classloader去getResources,打印出所有查找到的resources的rul。对于ResourceNotFoundException异常比较有用。

# 使用示例
# 默认按类加载器的类型查看统计信息
classloader
# 2 打印出hashcode和parent信息
classloader -l
# 3 打印出更多信息,谨慎使用
classloader -a
# 4 根据hashcode查看类加载器信息,查到类加载器所在的包
classloader -c 6bc7c054
# 5 用classloader去查找Resource
classloader -c 6bc7c054 -r META-INF/MANIFEST.MF
classloader -c 6bc7c054 -r java/lang/String.class
# 6 使用指定的classloader去加载类
classloader -c 6bc7c054 -load java.lang.String

6.7 monitor

作用:监控指定类方法的执行情况,如:成功次数、失败次数及异常率情况。默认监视120s才会给结果

# 使用示例
# 1 过5秒监控一次,类demo.MathGame中的primeFactors方法
monitor -c 5 demo.MathGame primeFactors

6.8 watch

作用:观察到指定方法的调用情况。入参、返回值、异常等。

# 使用示例
# 1 查看返回值
watch demo.MathGame primeFactors returnObj
# 2 查看深度为2的入参和返回值
watch demo.MathGame primeFactors "{params,returnObj}" -x 2
# 3 方法执行前获取的参数
watch demo.MathGame primeFactors "{params,returnObj}" -x 2 -b
# 4 查看当前对象的属性的值
watch demo.MathGame primeFactors "target" -x 2 -b
# 5 使用target.field_name访问当前对象的某个属性
watch demo.MathGame primeFactors "target.illegalArgumentCount" -x 2
# 6 同时观察方法调用前和方法返回后,参数里-n 2,表示只执行两次,-s 代表调用后。
watch demo.MathGame primeFactors "{params,target,returnObj}" -x 2 -b -s -n 2
#返回的数据一个是方法前,一个是方法后。

# 每个命令都可以带-h,查看帮助
watch -h
# 7 条件表达式的例子,输出第一个参数小于0的情况
watch demo.MathGame primeFactors "{params[0],target}" "params[0]<0"

6.9 trace

作用:对方法内部调用路径进行跟踪,并输出方法路径上的每个节点的耗时。

# 使用示例
# 1 trace函数指定类的指定方法。
trace demo.MathGame run
# 2 执行两次
trace demo.MathGame run -n 2
# 3 默认情况下,trace会跳过jdk的方法,如果要展示,使用下面的命令
trace --skipJDKMethod false demo.MathGame run -n 1
# 4 查找执行时间大于0.5ms的方法
trace demo.MathGame run '#cost > .5' -n 2

6.10 stack

作用:输出当前方法被调用的调用路径。

# 使用示例
# 1 获取primeFactors的调用路径
stack demo.MathGame primeFactors
# 2 条件表达式过滤,第0个参数的值小于0
stack demo.MathGame primeFactors 'params[0]<0' -n 2
# 3 查找执行时间大于0.5ms的方法
stack demo.MathGame run '#cost > .5' -n 2

6.11 tt

作用:time-tunnel时间隧道,记录指定方法每次调用的入参和返回值,并后期还可以对这些信息进行观测。

# 使用示例
# 1 最基本的使用,记录当前方法每次调用环境现场
tt -t demo.MathGame primeFactors
# 2 解决方法重载
tt -t *Test print params.length==1
# 3 通过制定参数个数的形式解决不同的方法签名,如果参数个数不一样,可以这样写
tt -t *Test print 'params[1] instanceof Integer'
# 4 解决制定参数
tt -t *Test print params[0].mobile=="123456"
# 5 查看cls清屏后的tt执行过的数据
tt -l
# 6 指定搜索的表达式
tt -s 'method.name=="primeFactors"'
# 7 查看index为多少(例:1011)的详细信息
tt -i 1011
# 8 重新调用一次
tt -i 1011 -p
# 9 重新调用的次数
tt -i 1011 -p --replay-times 2
# 10 两秒调用一次
tt -i 1011 -p --replay-times 2 --replay-interval 2000

6.12 options

作用:全局开关,慎重使用,可能会把jvm虚拟机搞挂了。

# 使用示例
# 1 查看所有的options
options
# 1 获取option的值
options json-format
# 2 打开执行结果存日志功能,输入如下命令即可
options save-result true

6.13 profiler

作用:生成火焰图

# 使用示例
# 1 默认情况下,生成的是CPU的火焰图,即event为CPU,可以用--event参数来指定。
profiler start
# 2 显示支持的事件
profiler list
# 3 查看状态
profiler status
# 4 停止火焰图
profiler stop
# 输出为:/Users/liangyafei/.arthas/lib/3.6.0/arthas/arthas-output/20220416-222956.html,用浏览器打开即可。
# 指定格式
profiler stop --format html
# 5 查看获取的样本数
profiler getSamples

火焰图示例:

总结

在阿里的实际工作当中,Arthas作为在线诊断的工具,我们常用的命令主要有watch以及jad、mc、redefine三组合,还有就是一些常见的jvm命令等辅助我们去查一些环境信息。

【温馨提示】

点赞+收藏文章,关注我并私信回复【面试题解析】,即可100%免费领取楼主的所有面试题资料!

相关推荐

Github霸榜的SpringBoot全套学习教程,从入门到实战,内容超详细

前言...

SpringBoot+LayUI后台管理系统开发脚手架

源码获取方式:关注,转发之后私信回复【源码】即可免费获取到!项目简介本项目本着避免重复造轮子的原则,建立一套快速开发JavaWEB项目(springboot-mini),能满足大部分后台管理系统基础开...

Spring Boot+Vue全栈开发实战,中文版高清PDF资源

SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础...

探秘Spring Cache:让Java应用飞起来的秘密武器

探秘SpringCache:让Java应用飞起来的秘密武器在当今快节奏的软件开发环境中,性能优化显得尤为重要。SpringCache作为Spring框架的一部分,为我们提供了强大的缓存管理能力,让...

3,从零开始搭建SSHM开发框架(集成Spring MVC)

目录本专题博客已共享在(这个可能会更新的稍微一些)https://code.csdn.net/yangwei19680827/maven_sshm_blog...

Spring Boot中如何使用缓存?超简单

SpringBoot中的缓存可以减少从数据库重复获取数据或执行昂贵计算的需要,从而显著提高应用程序的性能。SpringBoot提供了与各种缓存提供程序的集成,您可以在应用程序中轻松配置和使用缓...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

1,从零开始搭建SSHM开发框架(环境准备)

目录本专题博客已共享在https://code.csdn.net/yangwei19680827/maven_sshm_blog1,从零开始搭建SSHM开发框架(环境准备)...

做一个适合二次开发的低代码平台,把程序员从curd中解脱出来-1

干程序员也有好长时间了,大多数时间都是在做curd。现在想做一个通用的curd平台直接将我们解放出来;把核心放在业务处理中。用过代码生成器,在数据表设计好之后使用它就可以生成需要的controller...

设计一个高性能Java Web框架(java做网站的框架)

设计一个高性能JavaWeb框架在当今互联网高速发展的时代,构建高性能的JavaWeb框架对于提升用户体验至关重要。本文将从多个角度探讨如何设计这样一个框架,让我们一起进入这段充满挑战和乐趣的旅程...

【推荐】强&amp;牛!一款开源免费的功能强大的代码生成器系统!

今天,给大家推荐一个代码生成器系统项目,这个项目目前收获了5.3KStar,个人觉得不错,值得拿出来和大家分享下。这是我目前见过最好的代码生成器系统项目。功能完整,代码结构清晰。...

Java面试题及答案总结(2025版持续更新)

大家好,我是Java面试分享最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试场景题及答案。...

Java开发网站架构演变过程-从单体应用到微服务架构详解

Java开发网站架构演变过程,到目前为止,大致分为5个阶段,分别为单体架构、集群架构、分布式架构、SOA架构和微服务架构。下面玄武老师来给大家详细介绍下这5种架构模式的发展背景、各自优缺点以及涉及到的...

本地缓存GuavaCache(一)(guava本地缓存原理)

在并发量、吞吐量越来越大的情况下往往是离不开缓存的,使用缓存能减轻数据库的压力,临时存储数据。根据不同的场景选择不同的缓存,分布式缓存有Redis,Memcached、Tair、EVCache、Aer...