龙空技术网

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

面试题解析 339

前言:

现在小伙伴们对“阿里arthas官网”大体比较注重,看官们都想要知道一些“阿里arthas官网”的相关资讯。那么小编在网上汇集了一些对于“阿里arthas官网””的相关内容,希望我们能喜欢,各位老铁们快快来学习一下吧!

1 概述1.1 什么是Arthas

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

官网:

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  必须要有个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/.arthasrm -rf /Users/liangyafei/logs
3 atach一个进程3.1 一个案例
# 第一个窗口cd /Users/liangyafei/.arthas/lib/3.6.0/arthasjava -jar math-game.jar
3.2 粘附进程
#第二个窗口cd /Users/liangyafei/software/arthasjava -jar arthas-boot.jar# 如果报错端口号被占用,则使用下面的命令java -jar arthas-boot.jar --telnet-port 9998 --http-port -1# Linux命令查看被占用的端口号netstat -tnlp
3.3 浏览器连接Arthas

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 <value>]

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

# 使用示例# 1 显示线程1thread 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 查看PrintGCDetailsvmoption PrintGCDetails# 2 设置PrintGCDetailsvmoption 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 执行多行表达式,赋值给临时变量,返回一个Listognl '#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.MathGamesc demo.MathGame# 查看demo.MathGame详细信息sc demo.MathGame -d# 查看demo.MathGame详细信息,包括字段fieldsc 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和Locationjad --source-only demo.MathGame# 2 只反编译其中的一个方法jad java.lang.String trim
6.4 mc

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

# 使用示例# 1 编译Hello.javamc /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.javajad --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去查找Resourceclassloader -c 6bc7c054 -r META-INF/MANIFEST.MFclassloader -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个参数的值小于0stack 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 查看所有的optionsoptions# 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%免费领取楼主的所有面试题资料!

标签: #阿里arthas官网