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.
 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.

更多的思路

在很多代碼裏都有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],
]

鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章