当遇到 Java 线上问题时,如 CPU 飙升、负载突高、内存溢出等问题,可使用top,查命令,查网络,然后 jps、jstack、jmap、jhat、jstat、hprof ,这里主要介绍Arthas(阿尔萨斯)。
Arthas 是Alibaba开源的Java诊断工具。安装在系统所在服务器。可以帮助开发人员或者运维人员查找问题,分析性能,bug追踪。
开源地址:https://github.com/alibaba/arthas
官方文档:https://alibaba.github.io/arthas
得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。
安装的方式有好几种:
本篇介绍第一种方式,因为它简单而且想迁移的时候也超级方便(毕竟只需要把下载的jar包拷贝走就行了)。
可以在官方 Github 上进行下载,有时打不开。
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
如果速度较慢,可以尝试国内的码云 Gitee 下载。
curl -O https://arthas.gitee.io/arthas-boot.jar
本文介绍在windows环境下如何使用arthas,linux下大同小异。
在浏览器中直接输入https://arthas.gitee.io/arthas-boot.jar,下载arthas-boot.jar包。
本地运行程序,我这里随便写了一个查询人名的demo,同时启动一个线程,运行程序。
打开cmd终端,切换到放arthas-boot.jar的路径,输入
java -jar arthas-boot.jar
然后显示第4个运行的进程就是我的demo。
然后输入2,点击enter,启动成功。
web console
Arthas 目前支持 Web Console,在成功启动连接进程之后就已经自动启动,可以直接访问 http://127.0.0.1:8563/ 访问,页面上的操作模式和控制台完全一样。
可以在以上两个页面执行命令操作。
用thread命令列出线程的信息
这个命令会把所有线程按照cpu占用率从高到低列出来,如果线程太多,可以通过-n参数指定输出的行数。
面的输出结果可以看到id为某个数字的这个线程cpu占用率很过,然后再通过thread加线程id输出改线程的栈信息
还是用thread命令,参数是-b
这个命令和jstack工具检测死锁同样简单,不过个人认为jstack工具检测死锁其实要比这个更直观一些。
这个我们可以用dashboard命令来动态查看内存情况,ctrl+c可以停止刷新
如果内存使用率在不断上升,而且gc后也不下降,后面还发现gc越来越频繁,很可能就是内存泄漏了。
这个时候我们可以直接用heapdump命令把内存快照dump出来,作用和jmap工具一样
heapdump --live G:/jvm.hprof
然后把得到的dump文件导入eclipse,用MAT插件分析就行了。
arthas还提供了很多用于监控的命令,比如监控某个方法的执行时间,反编译线上的class文件,甚至在不重启java应用的情况下直接替换某个类。
在arthas交互环境中,可以输入help命令,然后会出现所有arthas支持的命令
如果不知道命令的用法,可以输入相应的命令后加参数–help,比如可以看一下watch命令的用法
不仅会显示出命令是干嘛用的,命令的完整参数,还很贴心地提供了一些具体的例子,参考开源地址:https://github.com/alibaba/arthas。
id 线程id
-n 指定最忙的的前n个线程并打印堆栈
b找出当前阻塞其他线程的线程
-i 指定cpu占比统计的采样时间间隔,单位为毫秒。
命令+类完全限定名+监测方法+表达式
watch com.example.arthas.arthasdemo.controller.HelloController getPerson "{params,returnObj}" -x 2
方法内部调用路径,并输出方法路径上的每个节点上耗时
trace com.example.arthas.arthasdemo.controller.HelloController getPerson
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
tt -t com.example.arthas.arthasdemo.controller.HelloController getPerson
表格字段说明
表格字段 字段解释
INDEX 时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。
TIMESTAMP 方法执行的本机时间,记录了这个时间片段所发生的本机时间
COST(ms) 方法执行的耗时
IS-RET 方法是否以正常返回的形式结束
IS-EXP 方法是否以抛异常的形式结束
OBJECT 执行对象的hashCode(),注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体
CLASS 执行的类名
METHOD 执行的方法名
sc -d com.example.arthas.arthasdemo.controller.HelloController
-d 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。
如果一个类被多个ClassLoader所加载,则会出现多次
quit —— 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown —— 关闭 Arthas 服务端,所有 Arthas 客户端全部退出 & 重置所有增强过的类,就不用单独调用reset
Arthas还提供 Web Console。
java -jar arthas-boot.jar --target-ip 192.168.168.67
在局域网内,其它机器可访问 http://192.168.168.67:8563
默认情况下,arthas只listen 127.0.0.1,所以如果想从远程连接,则可以使用 --target-ip参数指定listen的IP,更多参考-h的帮助说明。