Arthas诊断
阿里开源 Arthas 工具,线上诊断 Java 程序的神器。
一、Arthas简介

1.1 使用准备
## 1、下载 arthas 的包
wget https://alibaba.github.io/arthas/arthas-boot.jar
## 2、启动 arthas
java -jar arthas-boot.jar
## 3、arthas 启动后会自动检测存在的 java 进程
$ java -jar arthas-boot.jar
* [1]: 35542 com.yyq.bootstrap.jar
[2]: 71560 arthas-demo.jar
1
## 4、选择进程,使用相关命令
## 5、stop 命令可退出二、基础命令
2.1 jad(反编译)
## 查看 java 源码,可以用来诊断线上环境代码是否最新
jad demo.MathGame test2.2 watch(数据观测)
## 监听 demo.MathGame 类的 primeFactors 方法,展示 params[0] 第一个参数、returnObj 返回值、throwExp 报错,过滤条件 params[0].getKey == '12345',打印详细参数-v,收集n条数据-n
watch demo.MathGame primeFactors "{params[0],returnObj,throwExp}" "params[0].getKey == '12345'" -x 2 -v -n
## 过滤list数组中包含参数条件
wacth ... "params[0].parameters.indexOf('c1r4k4yv')>-1"2.3 trace(调用路径)
stack:当前方法被调用的调用路径(反向trace)
## 监控方法内部调用路径,并输出方法路径上的每个节点上耗时
trace demo.MathGame test2.4 sc(JVM 已加载的类信息)
## 查看JVM已加载的类信息
$ sc -d demo.MathGame
class-info demo.MathGame
code-source /private/tmp/math-game.jar
name demo.MathGame
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name MathGame
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@3d4eac69
+-sun.misc.Launcher$ExtClassLoader@66350f69
classLoaderHash 3d4eac69
Affect(row-cnt:1) cost in 875 ms.2.5 logger(logger 信息)
## 查询所有日志设置
$ logger
## 更改日志级别
$ logger -c [hashcode] --name ROOT --level debug2.6 tt(方法执行数据的时空隧道)
2.7 ognl表达式
如watch命令的过滤、计数等…
三、高级应用
3.1 Idea插件
arthas idea
3.2 线上热部署
3.3 获取任意bean
spring mvc应用,请求会经过一系列的spring bean处理,那么我们可以在spring mvc的类里拦截到一些请求。
$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 101 ms.
INDEX TIMESTAMP COST(ms IS-RE IS-EX OBJECT CLASS METHOD
) T P
------------------------------------------------------------------------------------------------------------------
1000 2019-01-27 16:31 3.66744 true false 0x4465cf70 RequestMappingHandlerAda invokeHandlerMethod
:54 pter那么怎样获取到spring context?
可以用tt命令的-i参数来指定index,并且用-w参数来执行ognl表达式来获取spring context:
$ tt -i 1000 -w 'target.getApplicationContext()'
@AnnotationConfigEmbeddedWebApplicationContext[
reader=@AnnotatedBeanDefinitionReader[org.springframework.context.annotation.AnnotatedBeanDefinitionReader@35dc90ec],
scanner=@ClassPathBeanDefinitionScanner[org.springframework.context.annotation.ClassPathBeanDefinitionScanner@72078a14],
annotatedClasses=null,
basePackages=null,
]
Affect(row-cnt:1) cost in 7 ms.从spring context里获取任意bean
获取到spring context之后,就可以获取到任意的bean了,比如获取到helloWorldService,并调用getHelloMessage()函数:
$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
@String[Hello World]
Affect(row-cnt:1) cost in 5 ms.3.4 获取数据库连接信息
找到项目中数据库相关组件,如:mybatis-spring
查询数据库组件中存在DataSource的相关类和方法
org.mybatis.spring.transaction.SpringManagedTransactionFactory#newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)通过tt方法检索DataSource中隐藏的数据库连接信息
tt -t org.mybatis.spring.transaction.SpringManagedTransactionFactory newTransaction -n 5
tt -i 1001 -w 'params[0].**'