一次jvm内存溢出问题排查

本文分析了一次因线程创建过多导致的服务内存溢出问题。通过jstack工具观察线程状态,发现大量线程处于阻塞状态。进一步分析发现是由于文件读写速度受限于系统对进程的同时打开文件数的限制,导致线程积压。最终通过调整系统参数及改进线程使用方式解决了问题。

线程创建过多导致服务内存溢出

一次jvm内存溢出问题排查

首先看下问题原因:
获取直接内存失败
上图的意思是获取直接内存失败,然后jvm建议减少堆的大小,或者减小每个线程的大小,或者增加系统内存

观察下线程的状态:
目前有十三万个线程池(代码编写存在问题,一般情况下不会有这么多线程池),且十三万的线程都处于阻塞状态
目前总共产生了十三万个线程池(代码编写存在问题,一般情况下不会有这么多线程池),且统计了一下,存在十三万的线程都处于阻塞状态

开始使用jstack -l pid 观察运行中的状态:
在高并发的情况下,线程都是在等待一个条件,说明目前是阻塞的情况,并且长时间无法释放锁
目前的线程是阻塞状态,且在等待一个锁

分析
从以上的状态来看,高并发情况下,程序一直在重复的创建线程池并运行任务,但是每个线程都阻塞在一个条件上了,不是高并发情况却不会存在这个问题;
这种情况存在一种可能性:消费问题,由于系统瓶颈导致大量线程获取不到锁,从而阻塞;
结果:
由于linux系统对进程的同时打开文件数的限制,导致高并发情况下的文件读写速度跟不上,引发了线程的积压,适量增大系统的limit数量:
vim /etc/security/limits.conf

*                soft    nofile          65536
*                hard    nofile          65536
root             soft    nofile          327680
root             hard    nofile          327680
*                soft    nproc           327680
*                hard    nproc           327680

由于是老代码,这里存在一个问题,这里的线程使用是存在问题的,不应该创建那么多的线程去执行任务,使用队列加线程池的方式是最佳的解决办法。如果存在任务积压,可以通过拒绝策略指定处理方式,而不是需要排查堆栈日志找问题;

参考资料
jvm崩溃日志分析
jstack日志分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值