Alibaba Arthas實踐--獲取到Spring Context,然後為所欲為
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
的請求
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
然後訪問一個網頁:http://localhost:8080/
可以看到Arthas會攔截到這個呼叫,index是1000,並且打印出:
$ watch com.example.demo.Test * 'params[0]@sss' $ 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. INDEXTIMESTAMPCOST(msIS-REIS-EXOBJECTCLASSMETHOD )TP ------------------------------------------------------------------------------------------------------------------ 10002019-01-27 16:313.66744truefalse0x4465cf70RequestMappingHandlerAdainvokeHandlerMethod :54pter
那麼怎樣獲取到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.
更多的思路
在很多程式碼裡都有static函式或者static holder類,順滕摸瓜,可以獲取很多其它的物件。比如在Dubbo裡通過SpringExtensionFactory
獲取spring context:
$ ognl '#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next, #context.getBean("userServiceImpl").findUser(1)' @User[ id=@Integer[1], name=@String[Deanna Borer], ]