记录unable to create new native thread 问题排查解决

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

问题描述

image.png

系统部署后遇到这个问题,因该环境提供的服务器配置偏低导出出现 java.lang.OutOfMemoryError: unable to create new native thread异常

问题分析

问题本质原因是项目创建了线程,而系统能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下:

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

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

问题解决

修改linux 最大进程数

1.查看用户打开到最大进程数

ulimit -a

max user processes    (-u) #系统限制某用户下最多可以运行多少进程过线程

2.修改进程数

1.在/etc/security/limits.conf 文件里添加如下内容

* soft nproc 65535      #打开进程数

* hard nproc 65535     #打开进程数

操作方法:

echo "* soft nproc 65535"  >> /etc/security/limits.conf

echo "* hard nproc 65535"  >> /etc/security/limits.conf

在 /etc/sysctl.conf 中添加 kernel.pid_max = 65535

# vim /etc/sysctl.conf

kernel.pid_max = 65535

或者

echo "kernel.pid_max = 65535" >> /etc/sysctl.conf

然后重启机器。

保存退出,输入以下命令执行使其生效  

其他问题排查

1.如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。

2.如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:

MaxProcessMemory 使用64位操作系统

VMMemory 减少 JVMMemory 的分配

ThreadStackSize 减小单个线程的栈大小

3.优化代码里面的线程池的线程配置,减少 JVMMemory 的分配

思考问题

具体的排查方法

1:通过堆栈信息,确定是否存在创建线程过多的问题

创建了多少线程?过度创建的线程的堆栈信息是什么?谁创建了这些线程?

一旦了解清楚,就能很快解决OOM的问题

2:增加操作系统的线程数

通过ulimit -a查看操作系统的最大线程数,这里假设为1024

如果应用程序所需的线程数超过1024,可以通过增大操作系统的线程数解决问题

3:增加机器内存

如果发现操作系统的线程数并未达到上限,说明应用程序需要更多的内存来创建线程

此时,增加机器内存便可以解决问题

4:减少JVM堆内存(-Xmx)

增加机器内存涉及硬件操作,不是最佳的选择

这时,不要忘记:线程不是在JVM的堆内存中创建的!

如果为JVM分配堆内存后,剩余内存较少,也会导致OOM: unable to create new native thread

在JDK 1.8中,需要减少–Xmx配置的值;在JDK 1.7中,需要减少堆内存和永久代内存( –Xmx和-XX:MaxPermSize)

5: 减少进程数

减少进程数,与较少堆内存相似

如果Java进程数过多,即使每个进程使用的堆内存不大,但累积起来也会导致剩余内存较少,从而出现OOM: unable to create new native thread

6: 减少线程栈大小(-Xss)

如果每个线程的堆栈较大,应用程序整体消耗的内存也会变大

可以根据实际情况,减少线程的堆栈大小,即通过–Xss设置线程堆栈为一个合理的、较小值

注意:-Xss不是设置得越小越好,过小的-Xss值会导致应用程序出现java.lang.StackOverflowError错误,甚至都无法启动JVM




目录
相关文章
|
SQL 存储 缓存
Paimon与Spark
Paimon与Spark
789 1
|
机器学习/深度学习 移动开发
解决mqtt连接报Connection lost (32109) - java.lang.IllegalArgumentException: Invalid UTF-8 char: [a]错误问题
最近生产环境在向mqtt客户端发布数据时反复出现一会断开一会连接错误,捕获的异常是java.lang.IllegalArgumentException: Invalid UTF-8 char: [a]。尝试各种方式都未找到问题的原因,最后在检查发送主题topic的时候发现所发送mqtt客户端的topic的结尾包含了换行符,最终才将问题得以解决。
6510 0
解决mqtt连接报Connection lost (32109) - java.lang.IllegalArgumentException: Invalid UTF-8 char: [a]错误问题
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
723 0
|
SQL 监控 关系型数据库
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
6334 0
|
12月前
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
13871 33
MCP客户端调用看这一篇就够了(Java版)
|
Java Linux iOS开发
8 种 Java- 内存溢出之五 -Unable to create new native thread
8 种 Java- 内存溢出之五 -Unable to create new native thread
在Linux中,如何查看某进程所打开的所有文件?
在Linux中,如何查看某进程所打开的所有文件?
|
Java API Maven
解决SLF4J和logback报错SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.
解决SLF4J和logback报错SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.
|
存储 前端开发 Java
SpringMVC 文件上传和下载
SpringMVC 文件上传和下载
308 0