记录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
820 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的结尾包含了换行符,最终才将问题得以解决。
6572 0
解决mqtt连接报Connection lost (32109) - java.lang.IllegalArgumentException: Invalid UTF-8 char: [a]错误问题
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
737 0
|
SQL 监控 关系型数据库
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
6472 0
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
14295 33
MCP客户端调用看这一篇就够了(Java版)
|
SQL 关系型数据库 MySQL
Flink CDC 3.4 发布, 优化高频 DDL 处理,支持 Batch 模式,新增 Iceberg 支持
Apache Flink CDC 3.4.0 版本正式发布!经过4个月的开发,此版本强化了对高频表结构变更的支持,新增 batch 执行模式和 Apache Iceberg Sink 连接器,可将数据库数据全增量实时写入 Iceberg 数据湖。51位贡献者完成了259次代码提交,优化了 MySQL、MongoDB 等连接器,并修复多个缺陷。未来 3.5 版本将聚焦脏数据处理、数据限流等能力及 AI 生态对接。欢迎下载体验并提出反馈!
1950 1
Flink CDC 3.4 发布, 优化高频 DDL 处理,支持 Batch 模式,新增 Iceberg 支持
|
Docker 容器
Docker部署minio-arm64版本,阿里官方推荐
Docker部署minio-arm64版本,阿里官方推荐
|
传感器 负载均衡 物联网
MQTT v5共享订阅是怎么回事?如何使用共享订阅提高消息订阅的灵活性和可伸缩性?
MQTT v5共享订阅是怎么回事?如何使用共享订阅提高消息订阅的灵活性和可伸缩性?
1177 1
|
Java Linux iOS开发
8 种 Java- 内存溢出之五 -Unable to create new native thread
8 种 Java- 内存溢出之五 -Unable to create new native thread
|
Java Linux Maven
IDEA如何用maven打包(界面和命令两种方式)
【10月更文挑战第14天】本文介绍了两种Maven项目打包方法:命令行与IDEA界面。首先确保已安装Maven并配置环境变量,通过`mvn -v`检查安装。命令行打包需进入项目目录,执行`mvn package`,之后在`target`目录查看结果。IDEA打包则需配置Maven路径,打开Maven Projects窗口,双击Lifecycle下的`package`阶段,同样在`target`目录查找生成文件,并在Build窗口查看日志以排查问题。
6727 1