无法执行任何java命令,报错OutOfMemoryError: Cannot create GC thread. Out of system resources

生产程序功能不执行了,远程定位时发现无法使用jps,jstack甚至java -version命令,所有的java命令都无法执行,报错为无法创建线程.
$jps -ml
Error occurred during initialization of VM
Cannot create VM thread. Out of system resources.

查看程序日志发现有unable to create new native thread类似无法创建线程的报错
内存及CPU空闲较多,资源充足排除内存不足的影响,只能怀疑是哪里限制了最大线程数.
查看线程数限制:ulimit -u
ulimit -a

cat /etc/security/limit.conf

cat /etc/sysctl.conf 
查看各系统用户的进程数的命令如下所示,执行后可得类似如下结果。命令中的L是将(Java线程)轻量级进程也计算在内
# ps h -Led -o user | sort | uniq -c | sort -n
用户进程数(LWP)的分布情况。命令如下,查询结果类似如下。
# ps -o nlwp,pid,lwp,args -u username | sort -n

线程数3万多,但还没有达到最大限制65536,继续查看其他地方有没有限制。

# /proc/sys/kernel/threads-max物理内存决定的系统进程数上限
# /proc/sys/kernel/pid_max这个值表示进程ID的上限
# /proc/sys/vm/max_map_count限制一个进程可以拥有的VMA(虚拟内存区域)的数量
cat /proc/sys/kernel/threads-max
cat /proc/sys/vm/max_map_count
cat /etc/security/limits.d/90-nproc.conf 
cat /proc/sys/kernel/pid_max
pid_max进程ID的上限默认为32768 ,现在的线程数很接近了,应该是这里限制了,原因找到了,但是为什么会创建这么多线程呢?如果线程一直增加,即使加大进程ID上限也早晚会达到的,必须找到根本原因。
查看重启后的线程数
ps h -Led -o user | sort | uniq -c | sort -n
发现每次程序运行一个Job之后,线程数就会增加一个,而且对比一段时间内的线程发现之前的线程没有释放,且增加的线程名都是pool-开头,说明是线程池内创建的线程。
jstack -l pid| grep pool- |wc -l
怀疑某个线程池的线程无法回收,排查代码发现某个同事写的bug(低级问题,必须甩锅啊), 创建线程池未关闭,线程池不关闭,其中的线程不会释放,且每次都错误的新建线程池而非提交任务到同一个线程池。错误不复杂,修改很简单,但是现象很诡异,定位过程很曲折。
 
参考:

https://access.redhat.com/solutions/22105

https://blog.csdn.net/beatle_1983/article/details/50435751

https://www.jianshu.com/p/0bf0b3f889d6

https://www.cnblogs.com/autopenguin/p/6184886.html

http://blog.chinaunix.net/uid-20662820-id-5690021.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章