解决 java.lang.OutOfMemoryError: unable to create new native thread

出现场景
最近在部署一个省的项目时,遇到这个问题,该环境提供的服务器配置偏低,而项目本身为了性能,大量的使用的线程,导出出现 java.lang.OutOfMemoryError: unable to create new native thread异常

异常分析
这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

MaxProcessMemory 指的是一个进程的最大内存
JVMMemory JVM内存
ReservedOsMemory 保留的操作系统内存
ThreadStackSize 线程栈的大小

在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生 java.lang.OutOfMemoryError: unable to create new native thread

解决思路
如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。
如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:
MaxProcessMemory 使用64位操作系统
VMMemory 减少 JVMMemory 的分配
ThreadStackSize 减小单个线程的栈大小
解决方案
适当牺牲性能,优化代码里面的线程池的线程配置。

减少 JVMMemory 的分配
由于博主的项目是通过 Kubernetes 管理的,可以直接在对应的 yml 文件添加 jvm 的启动参数

spec:
containers:
- image: dk.io/library/group-performance-service:0.0.8
env:
- name: "JAVA_OPTIONS"
value: "-Xms256m -Xmx512m -Xss1m"
name: res-gather

重启工程后解决问题

后续
通过上述改动,程序在运行一段时间后,依然报内存溢出的错误!!!😱😱😱内心奔溃
没办法,接着分析错误原因

异常分析
上述都是在考虑线程的问题,线程又受到服务器进程的限制,难道是服务器上的进程数超最大限制了??😌😌😌
1.查看最大进程数 

sysctl kernel.pid_max

2.查看当前进程数 

ps -eLf | wc -l

观察发现有时后台定时任务启动的时候,当前进程数会超过系统的最大进程数限制!!!确认是进程数满了。

解决方案
1.修改最大进程数后系统恢复

echo 1000000 > /proc/sys/kernel/pid_max

2.永久生效

echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
sysctl -p

观察一段时间,服务器再也没有报内存溢出错误,问题解决 😊😊😊


原文链接:https://blog.csdn.net/thwsir/java/article/details/86480956

posted @ 2020-05-12 09:45  MR__Wang  阅读(604)  评论(0编辑  收藏  举报