Arthas是阿里巴巴开源的Java诊断工具,采用命令行交互的形式进行问题的定位与诊断。它能够帮助你.
解决以下问题:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?
下面就实际常用到的功能做一些简单介绍:
Arthas 安装与使用
https://github.com/alibaba/arthas
在局域网的离线环境下,需要下载arthas的全量包
Idea Arthas 插件安装
可能你会觉得写Arthas的命令很繁琐,初学者写命令效率低,Idea中arthas插件可以解决这一问题。
在Idea插件中搜索“arthas”,下载“arthas-idea”插件,如下图所示:
使用步骤
- 将arthas包复制到服务器;
- 查找对应java服务的进程号;
[root@host-10-19-141-49 hik]# lsof -i:8041
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Jsvc 60164 root 398u IPv4 2662812937 0t0 TCP *:8041 (LISTEN)
- 执行以下命令,进入arthas命令界面;
- 选择对应的进程号(输入数字,选择具体的进程号);
常用基础命令:
help——查看命令帮助信息
cat——打印文件内容,和 linux 里的 cat 命令类似
pwd——返回当前的工作目录,和 linux 命令类似
cls——清空当前屏幕区域
session——查看当前会话的信息
reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所
有增强过的类
version——输出当前目标 Java 进程所加载的 Arthas 版本号
history——打印命令历史
quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
keymap——Arthas 快捷键列表及自定义快捷键
sysenv: Display the system env.
sysprop: Display, and change the system properties
reset: Reset all the enhanced classes
dump: Dump class byte array from JVM
options: View and change various Arthas options
getstatic Show the static field of a class
sc: Search all the classes loaded by JVM
sm: Search the method of classes loaded by JVM
classloader: Show classloader info
dashboard:显示出线程(按照 cpu 占用百分比倒排)、内存(堆空间实时情况)、GC
情况等数据
thread:用来查看当前 jvm 中的线程信息.
jvm:查看当前 jvm 信息
watch:能方便的观察到指定方法的调用情况,返回值、抛出异常、入参(特殊值、异常没有捕获排查)
watch [class-pattern] [method-pattern] [express] params
其中class-pattern为类名的表达式,method-pattern为方法名表达式,express为观察表达式,
params是可以添加的一些参数信息。具体可查看官方文档。
在使用Arthas前,定位排查数据问题主要有两种方式:
- 日志:排查前需要写入日志代码,重新打包部署,不适合生产环境。
- 远程Debug:需开设debug端口,安全性差,阻塞环境中的应用程序,对使用的其他人员产生影响,不利于合作。
而使用Arthas定位问题,对环境几乎无影响,定位效率高。
示例:
watch com.hikvision.omcmdb.web.model.ModelRestful deleteModelCategory
'{params,returnObj,throwExp}' -n 5 -x 3
-n 5 表示只执行五次,防止被刷屏
-x 2 来指定打印对象的属性遍历深度
trace:方法内部调用路径,并输出方法路径上的每个节点上耗时(性能问题,调用链问题)
trace命令查看方法内部的调用路径,并且可以查看每个路径上的耗时。其使用方式如下:
trace [class-pattern] [method-pattern] [condition-express] params
其中class-pattern为类名的表达式,method-pattern为方法名表达式,condition-express为条件表达式,params是可以添加的一些参数信息。具体可查看官方文档。
下面为一次使用trace命令定位接口超时问题实例
示例2
下面为一次使用trace命令定位接口超时问题实例:
一次通过F12发现控制台一个接口很长时间没有响应数据,该接口用于查看工单的待办数量,于是使用
trace命令监控该接口如下图所示:
可以看到方法内部调用OrderCommonService.orderStatistics()方法时耗时了60秒之多,严重超时了,
于是继续使用trace命令监控OrderCommonService.orderStatistics()方法进一步定位超时位置,如此方
式,最终定位出是由于调用HOSP的查询用户区域权限方法引发的超时。整个过程图如下所示:
trace com.hikvision.omcmdb.web.model.ModelRestful deleteModelCategory -n 5 --
skipJDKMethod false
monitor:方法执行监控(性能问题排查,一段时间内的性能指标) 统计每个接口的运行情况
$ monitor -c 5
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 156 ms.
timestamp class
method total success fail
avg-rt(ms) fail-rate
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
------------------------
2019-08-20 09:18:13
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo 1 1 0 9.01 0.00%
timestamp class
method total success fail
avg-rt(ms) fail-rate
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
------------------------
2019-08-20 09:18:18
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo 1 1 0 2.81 0.00%
timestamp class
method total success fail
avg-rt(ms) fail-rate
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
------------------------
2019-08-20 09:18:23
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo 0 0 0 0.00 0.00%
timestamp class
method total success fail
avg-rt(ms) fail-rate
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
------------------------
2019-08-20 09:18:28
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo 1 1 0 2.54 0.00%
stack:获取方法从哪里执行的调用栈(用途:源码学习调用堆栈,了解调用流程) 查看方法的调用路径
stack
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl saveDeployFaceDetailInfo
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 147 ms.
ts=2019-08-20 09:14:29;thread_name=XNIO-2 task-
125;id=101;is_daemon=false;priority=5;TCCL=org.springframework.boot.loader.LaunchedURL
ClassLoader@55183b20
@com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFac
eXRestServiceImpl.saveDeployFaceDetailInfo()
at
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:140)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.jav
a:294)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:248)
at
org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:235)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402)
at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209)
at
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletCo
ntainerDispatcher.java:227)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDis
patcher.java:56)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDis
patcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:129)
at
org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(Ap
plicationContextHeaderFilter.java:55)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:131)
at
org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebReque
stTraceFilter.java:111)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:131)
at
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFil
ter.java:99)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:131)
at
org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormCo
ntentFilter.java:109)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:131)
at
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMetho
dFilter.java:93)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java
:131)
at
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncod
ingFilter.java:197)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java
:107)
tt:方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并
能对这些不同的时间下调用进行观测
jad 反编译具体类
jad
com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl.DeployFace
XRestServiceImpl
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@c387f44
+-sun.misc.Launcher$ExtClassLoader@56de6d6b
Location:
/opt/opsmgr/web/components/xalarm.1/bin/xalarm-acs/lib/xalarm-acs-provider-
1.1.1000.RELEASE.jar
/*
* Decompiled with CFR 0_132.
*/
package com.hikvision.ga.xalarm.acs.modules.provider.balarm.api.deploy.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hikvision.ga.common.BasePage;
import com.hikvision.ga.common.BaseResult;
import com.hikvision.ga.common.BusinessException;
import com.hikvision.ga.logger.build.HikGaLoggerFactory;
import com.hikvision.ga.logger.log.HikGaLogger;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.dto.DeployFaceDTO;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.dto.DeployFaceForm;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.dto.ResourceDto;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.mapper.entity.DeployFace;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.query.dto.CondiFaceLibDTO;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.res.dto.DynTreeNode;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.res.dto.FaceScopeCheck;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.res.dto.Result4FaceLibDTO;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.res.dto.TreeNodeParams;
import com.hikvision.ga.xalarm.acs.balarm.api.deploy.service.DeployFaceXRestService;
import com.hikvision.ga.xalarm.acs.modules.deploy.service.DeployFaceBackIacService;
import com.hikvision.ga.xalarm.acs.modules.deploy.service.DeployFaceService;
import com.hikvision.ga.xalarm.acs.modules.deploy.service.DeployFaceSuperBrainService;
import com.hikvision.ga.xalarm.acs.modules.deploy.service.DeployService;