Arthas 3.5.1 发布:神级特性!内存搜索对象 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hengyunabc
V2EX    程序员

Arthas 3.5.1 发布:神级特性!内存搜索对象

  hengyunabc
hengyunabc 2021-05-18 11:30:10 +08:00 3936 次点击
这是一个创建于 1676 天前的主题,其中的信息可能已经有所发展或是发生改变。

Arthas是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。

以前使用watch等命令时,我们通常要先知道哪个类,调用了哪个函数,然后触发调用。这样有局限:

  1. 线上触发调用比较难
  2. 要 watch 到正确的函数可能要选择多次
  3. 条件表达式 /结果表达式 可能需要多次测试

另外,如果想要查找内存里的对象,需要 heapdump 再分析。

Arthas 在最新发布的 3.5.1 版本里,带来神级特性:通过vmtool命令,可以在 JVM 内存搜索对象。

vmtool 在线教程

下面以vmtool在线教程为例,演示vmtool命令的功能:

首先启动任意 spring boot 应用,比如:

wget https://github.com/hengyunabc/spring-boot-inside/raw/master/demo-arthas-spring-boot/demo-arthas-spring-boot.jar java -jar demo-arthas-spring-boot.jar 

然后用arthas attach 目标进程,成功之后就可以使用vmtool命令了:

wget https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar 

查找 jvm 里的字符串对象

首先,vmtool命令通过getInstances这个 action,在 JVM 里搜索字符串:

$ vmtool --action getInstances --className java.lang.String @String[][ @String[Sorry, deque too big], @String[head=%d tail=%d capacity=%d%n], @String[elements=%s%n], @String[sun/nio/ch/IOVecWrapper], @String[40252e37-8a73-4960-807e-3495addd5b08:1620922383791], @String[40252e37-8a73-4960-807e-3495addd5b08:1620922383791], @String[sun/nio/ch/AllocatedNativeObject], @String[sun/nio/ch/NativeObject], @String[sun/nio/ch/IOVecWrapper$Deallocator], @String[Java_sun_nio_ch_FileDispatcherImpl_writev0], ] 

limit 参数

通过 --limit参数,可以限制返回值数量,避免获取超大数据时对 JVM 造成压力。默认值是 10 。

所以上面的命令实际上等值于:

vmtool --action getInstances --className java.lang.String --limit 10 

如果设置--limit为负数,则遍历所有对象。

查找 spring context

以前的在线教程里,我们需要通过tt命令来拦载 spring 调用,然后获取到 spring context 。

通过vmtool命令,我们可以直接获取到 srping context:

$ vmtool --action getInstances \ --className org.springframework.context.ApplicationContext @ApplicationContext[][ @AnnotationConfigEmbeddedWebApplicationContext[org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12028586: startup date [Thu May 13 16:08:38 UTC 2021]; root of context hierarchy], ] 

指定返回结果展开层数

getInstances action 返回结果绑定到instances变量上,它是数组。

通过 -x/--expand 参数可以指定结果的展开层次,默认值是 1 。

vmtool --action getInstances --className org.springframework.context.ApplicationContext -x 2

获取 srping bean,执行表达式

getInstances action 返回结果绑定到instances变量上,它是数组。可以通过--express参数执行指定的表达式。

比如,查找所有的 spring beans 名字:

vmtool --action getInstances \ --className org.springframework.context.ApplicationContext \ --express 'instances[0].getBeanDefinitionNames()' 

比如,调用userController.findUserById(1)函数:

$ vmtool --action getInstances \ --className org.springframework.context.ApplicationContext \ --express 'instances[0].getBean("userController").findUserById(1)' @User[ id=@Integer[1], name=@String[name1], ] 

查找所有的 spring mapping 对象

vmtool --action getInstances --className org.springframework.web.servlet.HandlerMapping

$ vmtool --action getInstances --className org.springframework.web.servlet.HandlerMapping @HandlerMapping[][ @SimpleUrlHandlerMapping[org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@5d3819c8], @EmptyHandlerMapping[org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping@11d509ba], @RequestMappingHandlerMapping[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@56a5f2e3], @WelcomePageHandlerMapping[org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WelcomePageHandlerMapping@4c0a4ed3], @EmptyHandlerMapping[org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping@51e1f8c3], @BeanNameUrlHandlerMapping[org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@68c0a39c], @SimpleUrlHandlerMapping[org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@110b768d], ] 

查找所有的 javax.servlet.Filter

在 Arthas 的在线教程里,我们介绍过怎么排查 http 请求 404/401 的问题。使用的是 trace javax.servlet.Filter *命令。

现在使用vmtool命令,我们可以直接查找出所有的 Filter 对象,加速定位过程。

$ vmtool --action getInstances --className javax.servlet.Filter @Filter[][ @OrderedCharacterEncodingFilter[org.springframework.boot.web.filter.OrderedCharacterEncodingFilter@49b69493], @OrderedHiddenHttpMethodFilter[org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter@5477cb9e], @AdminFilter[com.example.demo.arthas.AdminFilterConfig$AdminFilter@3b625385], @WsFilter[org.apache.tomcat.websocket.server.WsFilter@14875f22], @OrderedRequestContextFilter[org.springframework.boot.web.filter.OrderedRequestContextFilter@6bed550e], @OrderedHttpPutFormContentFilter[org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter@3e538cba], ] 

指定 classloader name

在多 classloader 情况下,还可以指定 classloader 来查找对象:

vmtool --action getInstances \ --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader \ --className org.springframework.context.ApplicationContext 

指定 classloader hash

可以通过sc命令查找到加载 class 的 classloader 。

$ sc -d org.springframework.context.ApplicationContext class-info org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext code-source file:/private/tmp/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spring-boot-1.5.13.RELEASE.jar!/ name org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext ... class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@19469ea2 +-sun.misc.Launcher$AppClassLoader@75b84c92 +-sun.misc.Launcher$ExtClassLoader@4f023edb classLoaderHash 19469ea2 

然后用-c/--classloader 参数指定:

vmtool --action getInstances \ -c 19469ea2 \ --className org.springframework.context.ApplicationContext 

强制 GC

当启用 -XX:+DisableExplicitGC的 JVM 参数之后,调用System.Gc()

vmtool里提供了强制 GC 的功能:

vmtool --action forceGc 

如果应用配置了-verbose:gc参数,则可以在应用的标准输出里看到类似的日志:

[GC (JvmtiEnv ForceGarbageCollection) 25760K->17039K(349696K), 0.0015299 secs] [Full GC (JvmtiEnv ForceGarbageCollection) 17039K->16840K(353792K), 0.0154049 secs] 

致谢

  • vmtool功能是在社区开发者dragon-zhang(张子成)的最初 PR 上,多次讨论修改完成的,感谢他的工作,同时欢迎大家提出 PR,参与开发。

总结

上面只展示使用vmtool命令操作 spring context 的例子。实际上可以应用在很多方面,比如:

  • 查找 RPC 的 Provider/Consumer 实例
  • 查找 MQ 的订阅对象信息
  • 查找 Mybatis 的 mapping 对象

欢迎大家到 Issue 里分享使用经验: https://github.com/alibaba/arthas/issues

我们正在寻找小伙伴,特别是深圳的同学,欢迎大家加入。

12 条回复    2021-05-18 14:20:58 +08:00
hqs0417
    1
hqs0417  
   2021-05-18 11:35:54 +08:00
66666
dqzcwxb
    2
dqzcwxb  
   2021-05-18 11:52:34 +08:00
这个 cooooooooooooooooooool
AutumnVerse
    3
AutumnVerse  
   2021-05-18 11:54:30 +08:00 via Android
第一想法,这玩意拿来写外挂行吗?
lululau
    4
lululau  
   2021-05-18 11:58:36 +08:00
赞,要是能用 kotlin / clojure / groovy 作为 expression lang 就好了
young1lin
    5
young1lin  
   2021-05-18 12:19:38 +08:00
可以,很棒棒。

我试了下链接里的 demo,棒棒棒!那个招聘的要求有咩有更具体的呢,大致的方向我好专攻一下。
hengyunabc
    6
hengyunabc  
OP
   2021-05-18 12:48:55 +08:00
@lululau 有几个影响。
1. ClassLoader可能会有泄露,比如 groovy 就很多版本都有问题
2. arthas 目前要支持 jdk6
3. 这些语言体积通常比较大,使 arthas 本身体积增大
4. 会对 jvm 本身 meta space 造成压力
hengyunabc
    7
hengyunabc  
OP
   2021-05-18 12:49:51 +08:00
@young1lin
可以在公众号里加我微信,欢迎投递简历 :)
Ayanokouji
    8
Ayanokouji  
   2021-05-18 13:25:47 +08:00
还可以查 jvm 级别 cache
lululau
    9
lululau  
   2021-05-18 13:34:36 +08:00
@hengyunabc 是否可以做成可选项,比如在测试环境使用时,一般更在乎使用上是否便利,而对系统稳定性的影响在可接受的范围内用户是可以容忍或者说是忽略的
hAppyTreeFrienDs
    10
hAppyTreeFrienDs  
   2021-05-18 13:59:42 +08:00
6666
hengyunabc
    11
hengyunabc  
OP
   2021-05-18 14:09:04 +08:00
@lululau 没有太理解。是否使用 arthas,使用哪个命令,对用户来说本身就是自己做的选择。
v2orz
    12
v2orz  
   2021-05-18 14:20:58 +08:00
团队用了快两年,感谢
关于     帮助文档     自助推广系统     博客     API     a href="/faq" class="dark" target="_self">FAQ     Solana     3297 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 29ms UTC 04:22 PVG 12:22 LAX 20:22 JFK 23:22
Do have faith in what you're doing.
ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86