arthas icon indicating copy to clipboard operation
arthas copied to clipboard

arthas 定位 多线程WeakHashMap引起的死循环cpu跑满问题

Open WangJi92 opened this issue 4 years ago • 2 comments

一、背景

大早上 线上k8s 机子 某个机子 cpu 飙高,导致k8s 健康检查失败,线上环境会自动执行jstack,上传到oss 通知到 钉钉告警群,直接分析锁、cpu 高的线程。

二、过程分析

2.1 排查cpu 占用最高的线程

使用jstack 分析:

发现占用CPU最高的线程栈是: org.apache.commons.beanutils.MethodUtils#getMatchingAccessibleMethod

当然也可以使用arthas 的 thread -n 10 命令 ,由于自动监控抓取的,省去了这一步了。

一般的常规操作 jstack+top ,参考:

jstack 、top 文件也可以使用这个网站来分析

image

2.2 定位问题线程MethodUtils工具类

在线程栈里发现 org.apache.commons.beanutils.MethodUtils#getMatchingAccessibleMethod 异常代码行数和本地 比较对应不上!

image

2.3 sc -d 查看当前类来自哪个jar包

使用Arthas sc命令搜索发现有两个不同版本jar包,真香🤣。k8s服务器重启了也可以用sc命令非常方便地定位jar冲突问题。 image

2.4 多线程并发问题

org.apache.commons.beanutils.MethodUtils实际来自apache-beanutils依赖:

<dependency> 
  <groupId>apache-beanutils</groupId>  
  <artifactId>commons-beanutils</artifactId>  
 </dependency>  

那么应用里两个不同版本的apache-beanutils到底哪里冲突了呢?

1.7 版本

 static WeakHashMap cache =  new  WeakHashMap(); 

1.9 版本

 static Map<MethodDescriptor, Reference<Method>> cache = Collections
        ._synchronizedMap_( new WeakHashMap<MethodDescriptor, Reference<Method>>());

那么为什么1.7版本里的代码有问题呢?

  • 线程在WeakHashMap的get方法里面出不来了,一直在while循环里面。
  • 多线程并发get和put,然后get方法内的while循环一直找不到eq的对象,循环出不来。

参考:

解决办法: 排除掉低版本的apache-beanutils依赖。

WangJi92 avatar Feb 25 '21 06:02 WangJi92

妙啊

yuhui0531 avatar Sep 18 '21 01:09 yuhui0531

细节果然是魔鬼

FirmFainth avatar Nov 08 '22 03:11 FirmFainth