Alibaba Arthas实践--获取到Spring Context,然后为所欲为
hengyunabc opened this issue · 30 comments
背景
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],
]
链接
spring bean中要调用的方法参数是对象类型,这个要怎么调用呢?
spring bean中要调用的方法参数是对象类型,这个要怎么调用呢?
参考 https://commons.apache.org/proper/commons-ognl/language-guide.html "Calling Constructors"
spring bean中调用无异常抛出的方法成功,但调用有异常(加了注解事物)的方法时报java.lang.NoSuchMethodException错?有异常方法调用和普通的不一致吗?
tt -i 1125 -w 'target.getApplicationContext().getBean("XXX").XX()'
spring bean中调用无异常抛出的方法成功,但调用有异常(加了注解事物)的方法时报java.lang.NoSuchMethodException错?有异常方法调用和普通的不一致吗?
tt -i 1125 -w 'target.getApplicationContext().getBean("XXX").XX()'
应该是一个aop动态生成的类,有些行为可能不一样。可以自己在代码里试下。
请教个问题 获取到spring context之后,如调用bean方法getXXX("参数")方法,中文参数无法正确显示和传递到方法上执行,如何解决???
spring bean中要调用的方法参数是对象类型,这个要怎么调用呢?
参考 https://commons.apache.org/proper/commons-ognl/language-guide.html "Calling Constructors"
这个ognl语言不简单~~~
spring bean中要调用的方法参数是对象类型,这个要怎么调用呢?
参考 https://commons.apache.org/proper/commons-ognl/language-guide.html "Calling Constructors"
这个ognl语言不简单~~~
arthas 基本命令和 ognl 使用起来还是有点麻烦,毕竟不经常使用ognl语言,这里弄了一个小插件可以简化一些常用的命令的使用,具体可以参考 https://plugins.jetbrains.com/plugin/13581-arthas-idea
插件使用介绍 https://www.yuque.com/docs/share/fa77c7b4-c016-4de6-9fa3-58ef25a97948?#
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,
贴出全部的操作日志和结果
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
`[arthas@9]$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 451 ms, listenerId: 1
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
1000 2020-06-30 12:25:14 48.844374 true false 0x5c4714ef RequestMappingHandlerAdapter invokeHandlerMethod
1001 2020-06-30 12:25:21 9.525508 true false 0x5c4714ef RequestMappingHandlerAdapter invokeHandlerMethod
1002 2020-06-30 12:25:28 4.081598 true false 0x5c4714ef RequestMappingHandlerAdapter invokeHandlerMethod
[arthas@9]$
[arthas@9]$ tt -i 1000 -w 'target.getApplicationContext().getBean("dictService")'
@DictService$$EnhancerBySpringCGLIB$$eab4e97d[
CGLIB$BOUND=@boolean[false],
CGLIB$FACTORY_DATA=@EnhancerFactoryData[org.springframework.cglib.proxy.Enhancer$EnhancerFactoryData@5fed9c9e],
CGLIB$THREAD_CALLBACKS=@ThreadLocal[java.lang.ThreadLocal@1b5043a7],
CGLIB$STATIC_CALLBACKS=null,
CGLIB$CALLBACK_0=@DynamicAdvisedInterceptor[org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor@7143c0d6],
CGLIB$CALLBACK_1=@StaticUnadvisedInterceptor[org.springframework.aop.framework.CglibAopProxy$StaticUnadvisedInterceptor@319d69fe],
CGLIB$CALLBACK_2=@SerializableNoOp[org.springframework.aop.framework.CglibAopProxy$SerializableNoOp@4452aba9],
CGLIB$CALLBACK_3=@StaticDispatcher[org.springframework.aop.framework.CglibAopProxy$StaticDispatcher@15334a0b],
CGLIB$CALLBACK_4=@AdvisedDispatcher[org.springframework.aop.framework.CglibAopProxy$AdvisedDispatcher@6b0d9f2a],
CGLIB$CALLBACK_5=@EqualsInterceptor[org.springframework.aop.framework.CglibAopProxy$EqualsInterceptor@3185d92c],
CGLIB$CALLBACK_6=@HashCodeInterceptor[org.springframework.aop.framework.CglibAopProxy$HashCodeInterceptor@605b3356],
CGLIB$CALLBACK_FILTER=@ProxyCallbackFilter[org.springframework.aop.framework.CglibAopProxy$ProxyCallbackFilter@241305f2],
CGLIB$getValue$0$Method=@method[public java.lang.String cn.teleinfo.bussiness.embed.service.DictService.getValue(java.lang.String,java.lang.String)],
CGLIB$getValue$0$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@6fb75e44],
CGLIB$emptyArgs=@object[][isEmpty=true;size=0],
CGLIB$delete$1$Method=@method[public void cn.teleinfo.bussiness.embed.service.DictService.delete(java.lang.Iterable)],
CGLIB$delete$1$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@68446857],
CGLIB$save$2$Method=@method[public void cn.teleinfo.bussiness.embed.service.DictService.save(java.lang.Object)],
CGLIB$save$2$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@771790ca],
CGLIB$save$3$Method=@method[public void cn.teleinfo.bussiness.embed.service.DictService.save(cn.teleinfo.bussiness.embed.model.entity.SysDictPO)],
CGLIB$save$3$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@4eefdcfd],
CGLIB$findByKey$4$Method=@method[public java.util.List cn.teleinfo.bussiness.embed.service.DictService.findByKey(java.lang.String)],
CGLIB$findByKey$4$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@1b7fee1a],
CGLIB$findByParentId$5$Method=@method[public java.util.List cn.teleinfo.bussiness.embed.service.DictService.findByParentId(java.lang.Long)],
CGLIB$findByParentId$5$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@50322bf2],
CGLIB$findLinkage$6$Method=@method[public cn.hutool.json.JSONObject cn.teleinfo.bussiness.embed.service.DictService.findLinkage(java.lang.String,java.lang.String)],
CGLIB$findLinkage$6$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@1b6860fe],
CGLIB$pageQuery$7$Method=@method[public cn.teleinfo.bussiness.embed.model.P cn.teleinfo.bussiness.embed.service.DictService.pageQuery(java.lang.String,java.lang.String,java.lang.String,java.lang.Integer,java.lang.Integer)],
CGLIB$pageQuery$7$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@2b505f5a],
CGLIB$findAll$8$Method=@method[public java.util.List cn.teleinfo.bussiness.embed.service.BaseService.findAll()],
CGLIB$findAll$8$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@4f3b6b14],
CGLIB$findOne$9$Method=@method[public java.lang.Object cn.teleinfo.bussiness.embed.service.BaseService.findOne(java.io.Serializable)],
CGLIB$findOne$9$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@e17b4ba],
CGLIB$delete$10$Method=@method[public void cn.teleinfo.bussiness.embed.service.BaseService.delete(java.lang.Object)],
CGLIB$delete$10$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@56204a16],
CGLIB$delete$11$Method=@method[public void cn.teleinfo.bussiness.embed.service.BaseService.delete(java.io.Serializable)],
CGLIB$delete$11$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@7f236507],
CGLIB$save$12$Method=@method[public void cn.teleinfo.bussiness.embed.service.BaseService.save(java.lang.Iterable)],
CGLIB$save$12$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@6bd4d23c],
CGLIB$equals$13$Method=@method[public boolean java.lang.Object.equals(java.lang.Object)],
CGLIB$equals$13$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@58d50998],
CGLIB$toString$14$Method=@method[public java.lang.String java.lang.Object.toString()],
CGLIB$toString$14$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@cf1986e],
CGLIB$hashCode$15$Method=@method[public native int java.lang.Object.hashCode()],
CGLIB$hashCode$15$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@681edfaa],
CGLIB$clone$16$Method=@method[protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException],
CGLIB$clone$16$Proxy=@MethodProxy[org.springframework.cglib.proxy.MethodProxy@2596a5a7],
sysDictRepository=null,
repository=null,
]
Affect(row-cnt:1) cost in 140 ms.
`
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
。。这个是cglib的代理对象,搜索下cglib原理相关。
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
之前给同事排查遇到过,可以使用这个看一下!
tt -i 1000 -w '#userServers=target.getApplicationContext().getBean("userService"),@org.springframework.aop.support.AopUtils@getTargetClass(#userServers)'
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
之前给同事排查遇到过,可以使用这个看一下!
tt -i 1000 -w '#userServers=target.getApplicationContext().getBean("userService"),@org.springframework.aop.support.AopUtils@getTargetClass(#userServers)'
大佬 我是想获取到userService对象后调用对象的方法 你发的命令执行完后显示如下
[arthas@9]$ tt -i 1003 -w '#userService=target.getApplicationContext().getBean("userService"), @org.springframework.aop.support.AopUtils@getTargetClass(#userService)'
@Class[
ANNOTATION=@integer[8192],
ENUM=@integer[16384],
SYNTHETIC=@integer[4096],
cachedConstructor=null,
newInstanceCallerCache=null,
name=@string[cn.teleinfo.bussiness.embed.service.UserService],
allPermDomain=@ProtectionDomain[ProtectionDomain null
null
java.security.Permissions@1abd60cd (
("java.security.AllPermission" "" "")
)
],
useCaches=@boolean[true],
reflectionData=@SoftReference[java.lang.ref.SoftReference@16c8bcfb],
classRedefinedCount=@integer[0],
genericInfo=@ClassRepository[sun.reflect.generics.repository.ClassRepository@7bf1f2a0],
serialVersionUID=@long[3206093459760846163],
serialPersistentFields=@ObjectStreamField[][isEmpty=true;size=0],
reflectionFactory=@ReflectionFactory[sun.reflect.ReflectionFactory@2e5c7cb6],
initted=@boolean[true],
enumConstants=null,
enumConstantDirectory=null,
annotationData=@AnnotationData[java.lang.Class$AnnotationData@5f96cab8],
annotationType=null,
classValueMap=null,
]
Affect(row-cnt:1) cost in 2 ms.
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
。。这个是cglib的代理对象,搜索下cglib原理相关。
谢谢大佬,我查下资料
大佬 我是想获取到userService对象后调用对象的方法 你发的命令执行完后显示如下
看看这个文章-arthas 入门最佳实践直接使用arthas idea plugin 生成 通过静态的static 、或者tt 也就是你这种方式、或者watch 直接集成给你生成命令
tt -i 1000 -w 'target.getApplicationContext().getBean("userService")'
获取到的对象都是null
rootUserName=null,
sysUserRepository=null,
sysRoleRepository=null,
authService=null,
nbmsEntPrefixRepository=null,
nbmsEntRepository=null,
nbmsEntPrefixApplyRepository=null,
nbmsEntPrefixConfigService=null,
mailService=null,
shrPrefix=null,
eppEntService=null,
userService=null,
sysLogUserRepository=null,
repository=null,贴出全部的操作日志和结果
获取到的repository都是null,项目是springboot,持久层是jpa
。。这个是cglib的代理对象,搜索下cglib原理相关。
谢谢大佬,我查下资料
您好,我现在也遇到这个问题,请问怎么解决
great examples! mark~
mark
mark
大佬你好,我在使用中遇到一个问题,就是target.getApplicationContext()报了一个NoSuchMethodException的错误。所以在getBean()的时候更加拿不到了。我们使用的是springboot项目。
1、我的操作是这样的:
tt -t com.hm.mayson.module.recommend.service.link.CdssRuleLink profileRecommend -n 5
INDEX TIMESTAMP COST(m IS-RE IS-EX OBJECT CLASS METHOD
s) T P
1000 2021-08-27 16:5 120.84 true false 0x7100dea CdssRuleLink profileRecommend
8:12 4801
tt -i 1000 -w 'target.getApplicationContext()'
2、然后报了一个这样的错误:
ognl.MethodFailedException: Method "getApplicationContext" failed for object com.hm.mayson.module.recommend.service.link.CdssRuleLink@7100dea [java.lang.NoSuchMethodException: com.hm.mayson.module.recommend.service.link.CdssRuleLink.getApplicationContext()], visit /root/logs/arthas/arthas.log for more detail
3、arthas.log中的报错信息如下:
ognl.MethodFailedException: Method "getApplicationContext" failed for object com.hm.mayson.module.recommend.service.link.CdssRuleLink@7100dea
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1556)
at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1620)
at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at ognl.SimpleNode.getValue(SimpleNode.java:258)
at ognl.ASTChain.getValueBody(ASTChain.java:141)
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at ognl.SimpleNode.getValue(SimpleNode.java:258)
at ognl.Ognl.getValue(Ognl.java:470)
at ognl.Ognl.getValue(Ognl.java:572)
at ognl.Ognl.getValue(Ognl.java:542)
at com.taobao.arthas.core.command.express.OgnlExpress.get(OgnlExpress.java:37)
at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.processWatch(TimeTunnelCommand.java:366)
at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.process(TimeTunnelCommand.java:293)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodException: com.hm.mayson.module.recommend.service.link.CdssRuleLink.getApplicationContext()
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1497)
... 26 common frames omitted
2021-08-27 17:38:06 [arthas-command-execute] WARN c.t.a.c.c.m.TimeTunnelCommand -tt failed.
com.taobao.arthas.core.command.express.ExpressException: ognl.MethodFailedException: Method "getApplicationContext" failed for object com.hm.mayson.module.recommend.service.link.CdssRuleLink@7100dea [java.lang.NoSuchMethodException: com.hm.mayson.module.recommend.service.link.CdssRuleLink.getApplicationContext()]
at com.taobao.arthas.core.command.express.OgnlExpress.get(OgnlExpress.java:40)
at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.processWatch(TimeTunnelCommand.java:366)
at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.process(TimeTunnelCommand.java:293)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: ognl.MethodFailedException: Method "getApplicationContext" failed for object com.hm.mayson.module.recommend.service.link.CdssRuleLink@7100dea
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1556)
at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1620)
at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at ognl.SimpleNode.getValue(SimpleNode.java:258)
at ognl.ASTChain.getValueBody(ASTChain.java:141)
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at ognl.SimpleNode.getValue(SimpleNode.java:258)
at ognl.Ognl.getValue(Ognl.java:470)
at ognl.Ognl.getValue(Ognl.java:572)
at ognl.Ognl.getValue(Ognl.java:542)
at com.taobao.arthas.core.command.express.OgnlExpress.get(OgnlExpress.java:37)
... 14 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.hm.mayson.module.recommend.service.link.CdssRuleLink.getApplicationContext()
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1497)
... 26 common frames omitted
@yqt8926 现在可以用 vmtool 命令更方便 : https://arthas.aliyun.com/doc/vmtool ,把在线教程跑一下。
@yqt8926 现在可以用 vmtool 命令更方便 : https://arthas.aliyun.com/doc/vmtool ,把在线教程跑一下。
感谢感谢,已经获取到了。
tt -i 1002 -w 'target.getApplicationContext().getBean("tempController")'
在控制台看到,通过@resource、@Autowired注解注入的属性都是null:
tempService=null,
redisUtil=null,
busContractService=null,
projectCenterLogic=null,
busContractMapper=null,
@Miliving 上面的回复就有关于这个null的,这是cglib生成的代理类。
那标题是不是有点夸张了!!通常spring应用中bean基本都会有@resource或者@Autowired相互注入,然后通过这些注入的属性调用相关的方法,结果通过 tt 命令拿到的bean这些属性都是null,只能调用静态方法!!
那标题是不是有点夸张了!!通常spring应用中bean基本都会有@resource或者@Autowired相互注入,然后通过这些注入的属性调用相关的方法,结果通过 tt 命令拿到的bean这些属性都是null,则无法进行方法调用。只能调用静态方法!!
- 自己先去看下cglib的原理。这个cglib对象有一个field,是原始的对象,获取到之后,就有原始对象的所有东西了
- 通过cglib对象是能直接调用原来对象的函数的,不然自己在代码里
@Autowired
依赖的也是cglib对象,它是怎么能被调用的? - 现在更多用
vmtool
来搜对象,不需要用tt命令了。 https://arthas.aliyun.com/doc/vmtool.html
在上面的示例里:tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod。最好把-n 1加上,即tt -n 1 -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod。不然在线上会把所有流量拦截
执行后出现这个错误啥情况
Time fragment[1000] does not exist
[arthas@11232]$ tt -i 1002 -w 'target.getApplicationContext().getBean("fooService").save((#foo=new com.example.lewjun.model.Foo(), #foo.setName("LewJun"), #foo))'
@Boolean[true]
Affect(row-cnt:1) cost in 1 ms.
[arthas@11232]$ tt -i 1002 -w 'target.getApplicationContext().getBean("fooService").getById(6)'
@Foo[
id=@Integer[6],
name=@String[LewJun],
height=null,
sex=null,
]
Affect(row-cnt:1) cost in 1 ms.
[arthas@11232]$