背景
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。
Arthas提供了非常丰富的关于调用拦截的命令,比如 trace/watch/monitor/tt 。但是很多时候我们在排查问题时,需要更多的线索,并不只是函数的参数和返回值。
比如在一个spring应用里,想获取到spring context里的其它bean。如果能随意获取到spring bean,那就可以“为所欲为”了。
下面介绍如何利用Arthas获取到spring context。
Demo: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-arthas-spring-boot
Arthas快速开始:https://alibaba.github.io/arthas/quick-start.html
使用tt命令获取到spring context
Demo是一个spring mvc应用,请求会经过一系列的spring bean处理,那么我们可以在spring mvc的类里拦截到一些请求。
启动Demo: mvn spring-boot:run
使用Arthas Attach成功之后,执行tt
命令来记录RequestMappingHandlerAdapter#invokeHandlerMethod
的请求
1 |
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod |
然后访问一个网页: http://localhost:8080/
可以看到Arthas会拦截到这个调用,index是1000,并且打印出:
1 |
$ watch com.example.demo.Test * 'params[0]@sss' |
那么怎样获取到spring context?
可以用tt
命令的-i
参数来指定index,并且用-w
参数来执行ognl表达式来获取spring context:
1 |
$ tt -i 1000 -w 'target.getApplicationContext()' |
从spring context里获取任意bean
获取到spring context之后,就可以获取到任意的bean了,比如获取到helloWorldService
,并调用getHelloMessage()
函数:
1 |
$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()' |
更多的思路
在很多代码里都有static函数或者static holder类,顺滕摸瓜,可以获取很多其它的对象。比如在Dubbo里通过SpringExtensionFactory
获取spring context:
1 |
$ ognl '#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next, |