作为java开发工程师来说,不可避免会遇到的问题就是,在正式环境下你的java服务出现一些突发问题的快速排查,而排查时最难排查定位的问题莫过于一些内存溢出、cpu高占用和GC相关等异常。因此,一款能够快速通过堆栈、线程来快速定位正式环境线上问题点的工具就显得极为重要。而应运而生的arthas便是一款快速解决定位此类问题的工具,我们来看下arthas官方文档(官方文档:Arthas 用户文档 — Arthas 3.5.5 文档)对arthas工具的定位,了解下arthas的强大之处:
在命令行下面执行 curl -O https://arthas.aliyun.com/arthas-boot.jar 命令,便会帮你自动安装好一个arthas-boot.jar的java包,就这么简单这么任性。启动命令也非常简单,只需运行:java -jar xxx.jar命令即可(注:请在出现问题的对应服务器上面运行),但是在运行启动命令时,会遇到一些常见的坑,以下是我列出的一些常见问题。
如果你系统上使用的jdk是openjdk,在运行java -jar xxx.jar时,会出现Can not find java process. Try to run `jps` command lists the instrumented Java HotSpot VMs on the target system.Please select an available pid.的异常。那是因为其没有jps,arthas是用jps去找java进程的,解决方案有两种,第一种,将openjdk改为oracle jdk,这个就不展开讲了。第二种解决方案,便是直接lsof -i|grep 端口号找到你想要排查的java服务pid,然后直接在命令后跟上pid即可运行,例如pid为123,命令运行:java -jar xxx.jar 123
(2 运行启动命令时,遇到arthas Can not find tools.jar错误
当你运行启动命令java -jar xxx.jar时,如果遇到这个报错的话,可能是因为在运行时,无法找到对应jdk的路径,导致用java命令运行时,无法正常启动。这种情况只需先找到你jdk文件夹的路径,在bin目录下运行java -jar命令即可。例如jdk路径为/home/jdk1.8.0_161,命令运行:/home/jdk1.8.0_161/bin/java -jar xxxjar
(3 运行启动命令时,遇到Unable to open socket file: target process not responding or HotSpot VM not loaded错误
在运行启动命令时,还可能会出现这个问题,这个问题是因为在运行该java服务时,服务器登录的用户需要和目标进程具有相同的权限。比如,我是用tomcat用户发布java服务,但是我现在登录的用户是root,他们用户不一致,所以导致无法运行。
如何查看当前java服务是用户发布可以使用:ps aux|grep 端口号 来查看,第一行就是java服务运行时使用的用户,然后使用sudo su 用户名 命令切换用户到相同级别的用户,然后我们就可以快乐的运行arthas了。
ps:如果是不小心跟我一样,三个坑都踩到了,就按照我的方式,就可以正常使用了,附上启动命令运行成功图。
3.arthas的一些常见命令
(1)dashboard命令
该命令是我们最常使用的命令,它能够展示我们当前这个java服务对应的所有线程的运行状态、CPU占用率、线程ID等情况;展示java服务内存占用情况,包括所有GC各个分代的总量、使用量、占用率、GC次数;以及java服务对应的版本和位置。能够直接快速定位到问题点。如图
(2)thread命令
thread命令可以展示所有线程对应的运行情况。但是它最牛逼的地方在于,当我们遇到某个线程出现例如高CPU占用时,我们只要运行thread 线程ID 就可以立刻定位到是哪一行源代码在占用如此高的cpu,能够快速立刻的解决我们原本需要排查很久的问题。例如:
能够快速看出,出现问题的线程对应出问题的源码位置,对应到了arthasTest:java39行的地方。
(3)trace命令
trace命令可以说是arthas一个极其强大且实用的命令,他会把我们想要监听的方法进行长期监听,直到方法满足我们设置的调用次数,然后会返回监听的方法下的每一个子方法的代码耗时时间!这是一个非常实用的检测我们接口里面具体哪个方法占用最大的耗时操作,从而解决性能瓶颈!他的使用命令为:trace 类全限定名 方法名 -n 执行次数,例如:
trace com.ylzinfo.ylzinfoapi.talent.service.impl.HtContactServiceImpl SSOLogin -n 2
表示对HtContactServiceImpl下的SSOLogin方法进行长期监听,如果该方法被执行了两次,那么返回每个子方法的请求时长。如下图:
(4)jad命令
jad命令可以为我们反编译出class文件,将他编译成我们正常的java代码,jad命令后面跟对应要编辑的类的全类名。例如:jad com.sys.javaConfig.CorsConfig 他就会自动帮我们把线上的CorsConfig文件打印出来。
(4)tt命令
tt命令用于监控某个方法,能记录下当时方法调用的所有入参和返回值以及方法总体的执行情况。
其中,最常用的查看方法总体执行情况的命令是:tt -t 全类名 方法名。它能够帮你监听某个方法,当该方法被调用时,会输出当前调用请求的方法执行情况,如下图:
此外,当你需要对某个请求调用这个方法进行入参、返回值的查看时,使用这个命令:tt -i index的值 。 此时,就会打印出具体请求对应的访问这个方法的所有情况,如下图:
(5)jvm命令
这个命令主要用来查看当前jvm信息。只需命令行执行:jvm,他最主要的作用还是在最底下,能够查看该jvm运行期间线程的存活数量、而且能够看到当前是否存在死锁等,其中包括如下内容:
(6)sc、sm命令
这个命令主要查看JVM已加载的类信息、方法信息,它可以查看到这个类的各中位置信息,继承情况,加载情况等,常用的命令为:sc -d 类全限定名,例如:sc -d com.aaa.bbb
此外,还能查询该类的成员变量方法信息,使用sc -d -f 类全限定名来执行。此处就不贴图了。
然后sm命令和sc命令很相似,他是获取当前类下面的所有方法,及其入参返参等数据,使用sm -d 类全限定名 即可。
(7)headdump命令
这个命令的作用是导出当前jvm的 dump文件。命令很简单,只需执行:heapdump 导出的文件路径 即可,例如:heapdump /tmp/dump.hprof