阿里开源诊断工具-Arthas的使用。
参考:
https://segmentfault.com/a/1190000019413202
https://alibaba.github.io/arthas/install-detail.html
下载
curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc
方式一:
# 安装curl -O https://arthas.gitee.io/arthas-boot.jar# 启动arthas,会进入命令行交互状态java -jar arthas-boot.jar# 退出quit# 也可以指定IPjava -jar arthas-boot.jar --target-ip 0.0.0.0
方式二:
# 安装curl -L https://alibaba.github.io/arthas/install.sh | sh# 启动arthas,会进入命令行交互状态./as.sh# 查看arthas命令手册./as.sh -h
基础使用
选择要诊断的程序,进入命令行:

dashbord
通过dashboard命令可以实时查看应用监控数据

线程
输入thread命令,会显示所有线程的状态信息
输入thread -b 会显示当前处于BLOCKED状态的线程,可以排查线程锁的问题

查看具体线程:thread id
输入thread -n 3会显示当前最忙的3个线程,可以用来排查线程CPU消耗

JVM
输入jvm命令,查看jvm详细的性能数据

监视函数参数和返回值
watch com.alvin.controller.PageController getPage "{params,returnObj}" -x 2

监视函数调用时间
trace可以监视每一行代码执行的时间
trace com.alvin.controller.PageController getPage

idea插件
arthas idea https://plugins.jetbrains.com/plugin/13581-arthas-idea
自动生成代码监视语句。
常用功能
配置静态applicationContext
可以获取spring变量、调用spring方法。
1、放置application类。
ApplicationContextProvider.java
2、配置
3、复制命令,并执行

反编译

效果
获取spring对象
我们可以直接获取spring对象的属性,还能手动调用里面的方法。
源码

获取类加载器
静态属性
ognl -x 3 '@com.alvin.arthas.ArthasUtil@a' -c 20ad9418

静态方法
ognl -x 3 '@com.alvin.arthas.ArthasUtil@test("1")' -c 20ad9418

普通属性
ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#springContext.getBean("arthasUtil").b' -c 20ad9418

普通方法
ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#springContext.getBean("arthasUtil").test2("2")' -c 20ad9418

获取spring环境变量
x
ognl -x 3 '#springContext=@com.alvin.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("server.port")' -c 439f5b3d
统计函数执行效率
monitor
# 每十秒统计一次monitor com.alvin.controller.LightEventPublisher publish -c 10

监视方法的入参和出参
watch
监视方法的内部行执行时间
trace
其他
tt 函数隧道
记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
通过tt也可以获取spring容器。
获取上次执行类,-n 统计次数tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 1通过target获取spring容器tt -i 1000 -w 'target.getApplicationContext().getBean("arthasUtil").b' -c 20ad9418

查看有什么类
search class
查看有什么方法
search method
获取代理类(controller service)
1、工具类
package com.alvin.util;import org.springframework.aop.framework.AdvisedSupport;import org.springframework.aop.framework.AopProxy;import org.springframework.aop.support.AopUtils;import java.lang.reflect.Field;public class AopTargetUtils {/*** 获取 目标对象* @param proxy 代理对象* @return* @throws Exception*/public static Object getTarget(Object proxy) throws Exception {if(!AopUtils.isAopProxy(proxy)) {return proxy; //不是代理对象}if(AopUtils.isJdkDynamicProxy(proxy)) {return getJdkDynamicProxyTargetObject(proxy);} else { //cglibreturn getCglibProxyTargetObject(proxy);}}private static Object getCglibProxyTargetObject(Object proxy) throws Exception {Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");h.setAccessible(true);Object dynamicAdvisedInterceptor = h.get(proxy);Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");advised.setAccessible(true);Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();return target;}private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {Field h = proxy.getClass().getSuperclass().getDeclaredField("h");h.setAccessible(true);AopProxy aopProxy = (AopProxy) h.get(proxy);Field advised = aopProxy.getClass().getDeclaredField("advised");advised.setAccessible(true);Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();return target;}}
2、命令
ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#proxyBean=#springContext.getBean("lightEventPublisher"),@com.alvin.util.AopTargetUtils@getTarget(#proxyBean).a' -c 20ad9418
查看线程死锁
代码

查看死锁:

