arthas
arthas copied to clipboard
arthas 定位 多线程WeakHashMap引起的死循环cpu跑满问题
一、背景
大早上 线上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 文件也可以使用这个网站来分析
2.2 定位问题线程MethodUtils工具类
在线程栈里发现
org.apache.commons.beanutils.MethodUtils#getMatchingAccessibleMethod
异常代码行数和本地 比较对应不上!
2.3 sc -d 查看当前类来自哪个jar包
使用Arthas sc
命令搜索发现有两个不同版本jar包,真香🤣。k8s服务器重启了也可以用sc
命令非常方便地定位jar冲突问题。
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的对象,循环出不来。
参考:
- https://blog.csdn.net/weixin_33693070/article/details/85952993
- https://www.cnblogs.com/love-jishu/p/4244302.html
解决办法: 排除掉低版本的apache-beanutils
依赖。
妙啊
细节果然是魔鬼