Arthas 是什么

Arthas 是阿里巴巴开源的一款强大的 Java 应用诊断工具,在 Java 开发领域中,它犹如一把万能钥匙,为开发者解决各种线上问题提供了极大的便利。它采用命令行交互模式,支持 Web 端在线诊断,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。凭借着强大且丰富的功能,Arthas 能做到的事情超乎想象,能让开发者以全局视角实时查看应用的 load、内存、gc、线程等状态信息 ,并能在不修改应用代码的情况下,对业务问题进行深入诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

在 Java 应用的实际运行过程中,常常会遭遇各种复杂的问题。比如,当 CPU 使用率突然升高,我们迫切需要知道是哪个线程或者哪个方法占用了过多的 CPU 资源;又或者当程序出现响应缓慢的情况时,我们急需找出是哪些代码的执行耗时较长。以往,为了解决这些问题,开发者可能不得不添加大量的日志语句,然后重新部署应用,这一过程不仅繁琐,还可能对正在运行的业务产生影响。而 Arthas 的出现,彻底改变了这种局面。它可以在不重启 JVM 的情况下,实时对 Java 应用进行诊断,这意味着开发者无需中断业务,就能快速定位和解决问题,极大地提高了开发和运维的效率,减少了因问题排查而导致的业务中断时间。

启动 Arthas

Arthas 的安装过程并不复杂,它提供了多种安装方式,以满足不同用户和环境的需求。下面将详细介绍在不同系统中安装 Arthas 的具体步骤 。

下载 Arthas

Arthas 提供了多种下载途径,最为便捷的方式是通过官方推荐的 curl 命令从阿里云镜像站点下载 Arthas 启动脚本,命令如下:

curl -O https://arthas.aliyun.com/arthas-boot.jar

这条命令会直接从阿里云镜像站点下载arthas-boot.jar文件,适用于网络环境较好的情况,能够快速完成 jar 文件的下载。

启动 Arthas

启动 Arthas 的基本命令是:

java -jar arthas-boot.jar

执行该命令后,Arthas 会自动扫描当前系统中正在运行的 Java 进程,并列出一个进程列表。例如:

[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 11999 vlog-server-1.0.0-SNAPSHOT.jar

在这个列表中,每个进程都有一个对应的序号,以及进程的 PID 和主类信息。我们需要根据实际情况,选择要诊断的 Java 进程对应的序号,然后按下回车键,Arthas 就会连接到该进程,开始进行诊断工作。

启动后,按照提示选择需要监控的 Java 进程即可。成功启动后,还可以在浏览器输入http://127.0.0.1:8563/进入 Web 端界面进行操作。

Arthas 常用命令详解

Arthas 提供了丰富的命令,涵盖基础操作、JVM 相关、类和类加载器管理以及核心监视等多个方面,这些命令是深入诊断 Java 应用问题的关键工具 。下面将详细介绍一些常用命令及其作用和使用场景。

基础命令

  • help:这是一个非常实用的命令,用于显示 Arthas 所有命令的详细介绍和使用说明。当你对某个命令的参数或功能不太清楚时,直接输入help,然后加上具体的命令名称,就能获取该命令的详细帮助信息 。例如,想了解dashboard命令的使用方法,输入help dashboard,就会得到关于dashboard命令的参数解释、功能描述等内容,帮助你快速掌握其用法。

  • cat:与 Linux 系统中的cat命令类似,Arthas 中的cat命令用于打印文件内容。如果不指定文件路径,则会显示当前目录下的文件列表。例如,要查看当前目录下test.txt文件的内容,执行cat test.txt,命令执行后,文件test.txt的内容就会在终端中显示出来,方便查看和分析文本文件中的信息。

  • grep:该命令用于匹配查找,和 Linux 里的grep命令功能相似,但它只能用于管道命令。比如,当你想在系统属性中查找包含 “java” 字符串的行时,可以使用sysprop | grep java,这条命令会过滤出系统属性中所有包含 “java” 的行并显示出来。此外,还可以使用-n参数显示行号,如sysprop | grep java -n,这样在查看结果时,能更清晰地定位到具体的行 。

  • pwdpwd命令用于打印当前的工作目录,和 Linux 系统中的pwd命令作用一致。执行pwd后,会在终端中显示当前所在的目录路径,让你清楚了解当前的工作位置,方便进行文件操作和命令执行。

  • session:通过session命令可以查看当前会话的信息,包括进程的 ID、会话 ID 等。这些信息在多会话环境中非常有用,能够帮助你区分不同的会话,了解当前会话与目标 Java 进程的关联情况 。

  • resetreset命令用于重置增强后类,它会将被 Arthas 增强过的类全部还原。当你在使用 Arthas 进行诊断时,对某些类进行了增强操作,若后续不再需要这些增强,或者想恢复类的原始状态,就可以使用reset命令。例如,执行reset后,之前被增强的类会恢复到未增强前的状态,Arthas 服务端关闭时也会自动重置所有增强过的类 。

  • version:这个命令很简单,用于查看当前 Arthas 的版本号。在与其他开发者交流或者查看 Arthas 的功能更新时,了解版本号是很重要的,执行version,就能快速获取当前使用的 Arthas 版本信息 。

  • historyhistory命令用于查看历史命令记录,它会列出你在当前会话中执行过的所有命令。当你需要重复执行之前的某个命令,或者回顾之前的操作步骤时,history命令就能派上用场,通过查看历史命令,找到需要的命令并重新执行 。

  • quitquit命令用于退出当前 Arthas 客户端,但 Attach 到目标进程上的 Arthas 服务端还会继续运行,端口会保持开放,下次连接时可以直接连接上。例如,当你暂时完成了对某个 Java 进程的诊断,想退出当前客户端界面,但又希望 Arthas 服务端保持运行状态以便后续再次连接使用时,就可以执行quit命令 。

  • stop:与quit不同,stop命令用于关闭 Arthas 服务端,执行该命令后,所有 Arthas 客户端都会全部退出,Arthas 与目标 Java 进程的连接也会断开。如果确定不再需要使用 Arthas 对当前进程进行诊断,并且希望完全停止 Arthas 的运行,可以使用stop命令 。

  • keymapkeymap命令用于查看 Arthas 快捷键列表,了解这些快捷键可以提高操作效率。例如,ctrl + a可以跳到行首,ctrl + e可以跳到行尾等。通过熟悉和使用这些快捷键,能更便捷地在 Arthas 命令行中进行操作 。

JVM 相关命令

dashboard:这是一个非常直观的命令,用于显示当前系统的实时数据面板。面板中包含了丰富的信息,按qctrl + c可以退出显示。数据主要分为以下几部分:

  • 线程信息:展示 Java 级别的线程 ID(注意这个 ID 不能跟jstack中的nativeID一一对应)、线程名、线程组、线程优先级(1 - 10 之间的数字,越大表示优先级越高)、线程的状态(如RUNNABLEBLOCKEDWAITING等)、CPU 占用率(采样 100ms,将所有线程在这 100ms 内的 cpu 使用量求和,再算出每个线程的 cpu 使用占比)、线程运行总时间(数据格式为分:秒)、中断位状态以及是否是daemon线程。通过这些信息,可以快速了解当前线程的运行状态和资源占用情况 。

  • 内存使用情况:包括堆内存(heap,细分S0S1以及老年代等区域的使用情况)和非堆内存(nonheap)的使用信息,能直观地看到内存的分配和使用状况,对于排查内存相关的问题非常有帮助 。

  • 运行时环境:展示操作系统信息和 JVM 信息,如操作系统名称、版本,JVM 的版本、启动参数等,方便了解应用运行的环境基础信息 。

threadthread命令用于查看当前 JVM 的线程堆栈信息,它有多种用法:

  • 查看所有线程:直接输入thread,会显示所有当前正在运行的线程信息,默认打印第一页的线程,方便对线程整体情况有一个初步了解 。

  • 查找死锁:使用thread -b,可以一键找出当前阻塞其他线程的线程,在应用卡住,怀疑是某个线程拿住锁导致其他线程等待的情况下,这个命令非常有用 。

  • 查看指定线程的堆栈信息:输入thread [线程ID],即可打印某个指定线程的堆栈信息,帮助分析该线程的执行情况和问题 。

  • 打印最忙的线程thread -n [数量],例如thread -n 3,会展示当前最忙的前 3 个线程并打印堆栈,通过分析这些线程的堆栈信息,可以找出可能存在性能问题的线程 。

  • 查看某个状态的线程:如thread --state WAITING,可以查看处于等待状态的所有线程,有助于分析线程等待的原因 。

jvm:该命令用于查看当前 JVM 的整体信息,包括但不限于以下内容:

  • 线程相关:JVM 当前活跃的线程数、活跃的守护线程数、从 JVM 启动开始曾经活着的最大线程数、总共启动过的线程次数以及当前死锁的线程数。这些数据能帮助了解 JVM 线程的整体状况和历史情况 。

  • 文件描述符相关:JVM 进程最大可以打开的文件描述符数以及当前打开的文件描述符数,对于排查文件资源相关的问题有重要参考价值 。

  • 其他信息:还包括内存池、垃圾回收详情、类加载情况等 JVM 的关键信息,全面展示 JVM 的运行状态 。

syspropsysprop命令用于查看和修改 JVM 的系统属性:

  • 查看所有属性:直接输入sysprop,会列出 JVM 的所有系统属性及其对应的值 。

  • 查看单个属性:例如sysprop java.version,可以查看java.version属性的值,即当前 JVM 的 Java 版本 。

  • 修改单个属性:使用sysprop [属性名] [新值]的格式,如sysprop user.country US,可以将user.country属性的值修改为US。但需要注意,修改系统属性可能会对应用产生影响,应谨慎操作 。

sysenvsysenv命令用于查看当前 JVM 的环境属性(System Environment Variables),例如:

  • 查看所有环境变量:执行sysenv,会展示所有当前 JVM 的环境变量及其对应的值 。

  • 查看单个环境变量:如sysenv USER,可以查看USER环境变量的值,了解当前用户信息 。

vmoptionvmoption命令用于查看和更新 VM 诊断相关的参数:

  • 查看所有的选项:输入vmoption,会列出所有的 VM 诊断选项及其当前值 。

  • 查看指定的选项:例如vmoption PrintGCDetails,可以查看PrintGCDetails选项的值,判断是否开启了详细的垃圾回收日志打印 。

  • 更新指定的选项:使用vmoption [选项名] [新值]的格式,如vmoption PrintGCDetails true,可以将PrintGCDetails选项的值设置为true,开启详细的垃圾回收日志打印 。

getstatic:通过getstatic命令可以方便地查看类的静态属性,语法为getstatic [类名] [属性名]。例如,getstatic com.vvhz.vlog.oss.util.OssUtil videoExtensions,可以显示OssUtil类中静态属性videoExtensions的值,对于分析类的静态成员变量状态很有帮助 。

[arthas@11999]$ getstatic com.vvhz.vlog.oss.util.OssUtil videoExtensions
field: videoExtensions
@HashSet[
    @String[mp4],
    @String[wmv],
    @String[flv],
    @String[rmvb],
    @String[avi],
    @String[mov],
    @String[mpeg],
    @String[mkv],
    @String[3gp],
    @String[webm],
]
Affect(row-cnt:1) cost in 15 ms.

ognlognl命令用于执行 OGNL 表达式,这是从 3.0.5 版本新增的功能。OGNL(Object - Graph Navigation Language)是一种强大的表达式语言,在 Arthas 中使用它可以实现很多灵活的操作。详细请查看Arthas中Ognl表达式示例

类和类加载器命令

scsc(Search Class)命令用于搜索已加载的类,使用方法为sc [class - pattern],例如sc *Test*,会查找所有包含 “Test” 的类。这个命令在确认某个类是否被加载到 JVM 中时非常有用,通过类名表达式匹配,可以快速定位到需要的类 。

[arthas@11999]$ sc *OssUtil
com.vvhz.vlog.oss.util.OssUtil
Affect(row-cnt:1) cost in 122 ms.

smsm(Search Method)命令用于搜索已加载类中的方法,使用方法为sm [class - pattern] [method - pattern],如sm *OssUtil uploadToOss,可以检查OssUtil类中是否存在uploadToOss方法,或者查看该方法是否被重载等情况 。

[arthas@11999]$ sm *OssUtil uploadToOss
com.vvhz.vlog.oss.util.OssUtil uploadToOss(Lorg/springframework/web/multipart/MultipartFile;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;
com.vvhz.vlog.oss.util.OssUtil uploadToOss(Ljava/io/File;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;
Affect(row-cnt:2) cost in 79 ms.

jadjad(Java Decompiler)命令用于反编译指定的已加载类,使用方法为jad [class-name],例如jad com.vvhz.vlog.oss.utilOssUtil。当没有类的源码,但又需要查看其实现时,jad命令就能将已加载的class文件反编译成 Java 源代码展示出来,方便分析类的代码逻辑 。

mcmc(Memory Compiler)是内存编译器,用于将 Java 文件编译成字节码和内存中的类文件。在需要动态编译 Java 代码时,mc命令就可以发挥作用,例如在诊断过程中,根据实际情况编写一些临时的 Java 代码并进行编译运行 。

redefineredefine命令用于加载外部.class文件,实现类的重新定义。语法为redefine [class-file-path],当对类进行了修改,生成了新的.class文件后,可以使用redefine命令将新的.class文件加载到 JVM 中,实现类的动态更新,而无需重启 JVM 。

dumpdump命令用于将已加载类的字节码文件保存到特定目录,默认路径为~/logs/arthas/classdump/,不同的类加载器加载的类会放在不同的目录下。例如,dump java.lang.String,会把String类的字节码文件保存到默认目录下;dump demo.*,会把demo包下所有的类的字节码文件保存到默认目录,方便后续对字节码文件进行分析和研究 。

classloaderclassloader命令用于获取类加载器信息,它有多种用法:

  • 默认按类加载器的类型查看统计信息:直接输入classloader,会统计并展示 JVM 中所有类加载器的类型和相关统计信息 。

  • 按类加载器的实例查看统计信息:使用classloader -l,可以看到类加载器的实例信息,包括类加载器的hashCode

  • 查看 ClassLoader 的继承关系classloader -t,可以查看类加载器之间的继承关系,了解类加载的层级结构 。

  • 通过类加载器的 hash,查看此类加载器实际所在的位置classloader -c [类加载器hash],例如classloader -c 28bb0d54,可以查看hash28bb0d54的类加载器的实际位置信息 。

  • 使用 ClassLoader 去查找类的 class 文件所在的位置classloader -c [类加载器hash] -r [类名.class],如classloader -c 28bb0d54 -r java/lang/String.class,可以查找指定类加载器加载的String.class文件所在的位置 。

  • 使用 ClassLoader 去加载类classloader -c [类加载器hash] --load [类名],例如classloader -c 70dea4e --load java.lang.String,可以使用指定的类加载器加载String类 。

核心监视命令

monitormonitor命令用于监控指定类中方法的执行情况,语法为monitor [class - pattern] [method - pattern] [-c cycle],其中-c参数表示统计周期(cycle of output),默认值为 120 秒。例如,monitor -c 5 demo.MathGame primeFactors,表示每 5 秒监控一次demo.MathGame类中primeFactors方法的执行情况,监控的维度包括:

  • timestamp:时间戳,记录监控数据的时间 。

  • class:Java 类名 。

  • method:方法名(包括构造方法、普通方法) 。

  • total:调用次数 。

  • success:成功次数 。

  • fail:失败次数 。

  • rt:平均耗时 。

  • fail - rate:失败率 。通过这些监控数据,可以直观地了解方法的执行效率和稳定性,快速发现可能存在问题的方法 。

watchwatch命令用于观察指定方法的调用情况,能观察到的范围包括返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。其参数较多,主要是因为它能在 4 个不同的场景观察对象,参数说明如下:

  • class - pattern:类名表达式匹配 。

  • method - pattern:方法名表达式匹配 。

  • express:观察表达式,由 OGNL 表达式组成,例如"{params, returnObj}",表示观察方法的入参和返回值 。

  • condition - express:条件表达式,用于过滤满足特定条件的方法调用 。

  • [b]:在方法调用之前观察(before) 。

  • [e]:在方法异常之后观察(exception) 。

  • [s]:在方法返回之后观察(success) 。

  • [f]:在方法结束之后(正常返回和异常返回)观察(finish) 。

  • [E]:开启正则表达式匹配,默认为通配符匹配 。

  • [x:]:指定输出结果的属性遍历深度,默认为 1 。例如,watch demo.MathGame primeFactors "{params, returnObj}" -x 2,表示观察demo.MathGame类中primeFactors方法的入参和返回值,结果属性遍历深度为 2;watch demo.MathGame primeFactors "{params, returnObj}" -x 2 -b,表示在方法调用前观察入参,此时因为方法还未执行,所以获取不到返回值 。通过watch命令,可以深入分析方法执行过程中的数据传递和异常情况,快速定位方法执行中的问题 。

tracetrace命令用于对方法内部调用路径进行追踪,并输出方法路径上每个节点的耗时,语法为 `trace [class-pattern]

文章作者: Z
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 微博客
基础 运维 工具
喜欢就支持一下吧