Linux服务器最大线程数限制 OutOfMemoryError: unable to create new native thread

本文解决了一个在Linux环境下启动Java项目时遇到的OutOfMemoryError问题,详细介绍了如何排查和解决由系统参数限制导致的无法创建新线程错误,包括调整jvm参数、检查系统线程限制和修改最大进程数。

研发环境上的Linux项目启动报错:Caused by: java.lang.OutOfMemoryError: unable to create new native thread

开始以为是内存不足导致无法创建线程,把jvm的-Xms,-Xmx的2个参数都加大一倍:-Xms2048m -Xmx2048m。把-Xss参数调小,还是启动失败。应该是系统方面的限制了,这台机器上搞了100个过tomcat进程,还有不少其他软件,东西比较多且杂。确认过机器的内存还是足够的,先排查系统参数,之后再清理垃圾资源了。

系统可生成最大线程数
cat /proc/sys/kernel/threads-max
这个值很大,tomcat进程的全部线程数肯定没有超过它,如果实际线程数比它大可改大(实际可能是代码问题,开启了太多线程)。

进程最大线程数
ps -eLf | grep 项目名 | wc -l 查看单个项目线程数,启动失败的这个项目线程数一般在600左右
cat /proc/sys/vm/max_map_count
65530
这个值没有问题,jvm的启动参数为-Dconfig.server.maxThreads=3000,也没有问题

用户最大进程数
ulimit -a
其中max user processes就是表示用户的最大进程数,我的这个值很大,进程数也没有超过它。如果超过的话,可以修改最大进程数的配置
vi /etc/security/limits.d/90-nproc.conf
* soft nproc 1024
root soft nproc unlimited
上面可以看除了root用户外的所有用户均限制为1024,因此通过可以注释此行或者将值改大,保存后修改立刻生效
#* soft nproc 1024
root soft nproc unlimited

整个系统已用的线程或进程数
cat /proc/sys/kernel/pid_max
该值是32678(32位Linux系统可创建的最大pid数是32678),查询当前整个系统已用的线程或进程数:pstree -p | wc -l,结果比32678稍小,问题就在这了

vim /proc/sys/kernel/pid_max,改为65535保存退出的时候报错如下
/proc/sys/kernel/pid_max E667 Fsync failed
改成下面方式即可:
echo "65535" > /proc/sys/kernel/pid_max
不需要重启,保存后立刻生效,重启项目终于好了

原文:https://blog.youkuaiyun.com/u013673976/article/details/51788566 
 

<think>嗯,用户这次提出了一个很具体的JVM错误处理问题,需要解决"OutOfMemoryError: unable to create new native thread"。从引用内容看,用户应该是个Java后端开发者,可能在处理高并发场景时遇到了线程创建瓶颈。 用户提供的四个引用很有价值,我需要整合这些信息给出系统化的解决方案。引用1和2解释了错误的本质是操作系统层面无法分配线程资源,引用3给出了线程池配置的反例和正例,引用4则提供了关键的线程数计算公式。看来用户已经做过基础调研,现在需要的是落地方案。 这个问题的复杂性在于涉及三个层面:JVM配置、操作系统限制、代码实现。我应该先帮用户理清排查路径: 第一层是操作系统限制,包括用户线程数限制(ulimit -u)和系统总线程数上限(/proc/sys/kernel/threads-max); 第二层是JVM内存分配,需要确认堆内存(-Xmx)没有占用过多导致原生内存不足; 第三层是应用层,重点检查线程池实现是否合理。 特别要注意引用3警示的无界线程池风险,这个在生产环境很常见。用户可能忽略了线程池关闭逻辑,所以需要强调addShutdownHook的使用。另外32位JVM的局限性也需要提醒,现在虽然少见但仍有遗留系统在使用。 解决方案要突出可操作性: 1. 量化分析方面,必须给出具体的计算公式(基于引用4),并举例说明如何调整-Xss参数; 2. 线程池配置要区分不同场景,比如IO密集型和计算密集型应用的线程池设置差异; 3. 补充引用没提到的Linux内核参数调整方案,比如vm.max_map_count的优化。 用户可能还会关心监控手段,可以准备后续回答如何通过jstack或arthas定位线程泄露。不过当前回复先聚焦基础解决方案,避免信息过载。最后用相关问题引导用户深入,特别是关于线程泄露检测这个隐患点。 </think>解决`OutOfMemoryError: unable to create new native thread`问题需要从**操作系统限制**、**JVM配置**和**代码优化**三方面入手,以下是系统化解决方案: --- ### 一、操作系统级调整(需root权限) #### 1. **扩大用户线程数限制** ```bash # 查看当前限制(普通用户) ulimit -u # 永久修改限制(需root) echo "* soft nproc 65535" >> /etc/security/limits.conf echo "* hard nproc 65535" >> /etc/security/limits.conf # 检查系统总线程数上限 cat /proc/sys/kernel/threads-max # 默认约总内存/128KB echo 120000 > /proc/sys/kernel/threads-max # 临时调整 ``` > **关键点**:单个用户线程数限制(`nproc`)和系统总线程数(`threads-max`)共同约束最大线程数[^1][^2]。 #### 2. **减少线程栈大小(需权衡)** JVM参数调整: ```bash -Xss256k # 默认1MB(Linux/x64),降至256KB可创建更多线程 ``` > **风险**:栈溢出风险增加,递归调用需谨慎[^4]。 --- ### 二、JVM内存优化 #### 1. **控制堆内存占用** 根据公式: $$ \text{可用线程数} = \frac{\text{MaxProcessMemory} - \text{JVMMemory} - \text{ReservedOsMemory}}{\text{ThreadStackSize}} $$ 减少`-Xmx`可释放更多内存给线程栈: ```bash -Xmx2g # 示例:降低堆内存 ``` #### 2. **使用64位JVM** 32位JVM进程内存限制通常为**2~4GB**,而64位JVM可突破此限制[^2]。 --- ### 三、应用代码优化 #### 1. **避免无界线程池** ```java // 错误:可能无限创建线程 ExecutorService pool = Executors.newCachedThreadPool(); // 正确:使用固定大小线程池 ExecutorService pool = Executors.newFixedThreadPool(50); ``` 添加关闭钩子确保资源释放: ```java Runtime.getRuntime().addShutdownHook(new Thread(pool::shutdown)); ``` #### 2. **检测线程泄漏** ```bash # 监控线程数增长 jstack <pid> | grep 'java.lang.Thread.State' | wc -l ``` 持续增长的线程数表明存在泄漏(如未关闭的HTTP连接、未shutdown的线程池)[^3]。 --- ### 四、终极方案:架构升级 当单机线程数仍不足时: 1. **垂直拆分**:将单体应用拆分为微服务,分散线程压力 2. **异步化改造**:用消息队列(如Kafka)替代同步线程调用 3. **协程替代线程**:使用Quasar或Project Loom的虚拟线程 --- ### 问题排查流程图 ```mermaid graph TD A[发生OOM: unable to create native thread] --> B{检查ulimit -u} B -->|过低| C[调整nproc限制] B -->|正常| D{检查线程总数} D -->|接近threads-max| E[扩大系统线程数] D -->|未达上限| F{检查JVM配置} F -->|堆内存过大| G[减小-Xmx] F -->|栈内存过大| H[减小-Xss] F -->|配置合理| I[检查线程泄漏] I -->|存在泄漏| J[修复未关闭的线程/连接] I -->|无泄漏| K[架构升级] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值