答案是java.lang.OutOfMemoryError: unable to create new native thread,该错误本质是操作系统无法为JVM分配新线程资源,主因是线程数超系统限制(如ulimit -u)或单线程栈(-Xss)过大导致总内存耗尽,需从OS限制、JVM配置和代码线程管理三方面协同排查。

Java 中线程创建失败,最典型的报错是 java.lang.OutOfMemoryError: unable to create new native thread。它不是 JVM 堆内存不足,而是操作系统层面无法为新线程分配资源导致的——本质是“线程数超限”或“线程栈总开销超标”。排查需跳出 JVM 视角,从 OS 限制、JVM 配置、代码行为三方面入手。
看报错日志,确认是不是 native thread 相关错误
先确认异常类型是否为:
java.lang.OutOfMemoryError: unable to create new native thread
这个错误明确指向线程创建失败,和 Java heap space 或 Metaspace 等堆内错误有本质区别。一旦出现,说明 JVM 尝试调用 pthread_create(Linux)或 CreateThread(Windows)失败,OS 拒绝了请求。
查系统级限制:ulimit 和内存余量
每个进程能创建的线程数受操作系统硬性约束:
- 运行
ulimit -u查当前用户允许的最大进程/线程数(例如 4096),Java 进程里所有线程(包括 GC 线程、JIT 线程、业务线程)都算在内 - 运行
free -h和cat /proc/meminfo | grep MemAvailable看可用内存。线程栈默认占 1MB(-Xss1m),1000 个线程就占 1GB 虚拟内存;若物理内存或 swap 不足,也会创建失败 - 检查是否启用了 cgroup 限制(如 Docker 容器中
memory.limit_in_bytes或pids.max),这些会覆盖 ulimit
核对 JVM 线程相关配置
重点看两个参数是否“打架”:
-
-Xss:单线程栈大小。设得过大(如 -Xss2m)会显著减少可创建线程总数;设得太小(如 -Xss128k)可能导致 StackOverflowError。生产环境推荐 256k–512k -
ThreadPoolExecutor的maximumPoolSize:如果无节制设置成 1000+,又没配合理队列和拒绝策略,高并发下会瞬间拉满线程数 - 注意:线程池 corePoolSize 设为 0 且 allowCoreThreadTimeOut = true 时,空闲核心线程也会被回收,有助于控线程数
抓现场:用 jstack + top 定位线程爆炸点
服务已卡顿或频繁报错时:
- 执行
top -H -p找 CPU 或数量异常高的线程 - 用
printf '%x\n'把线程 ID 转十六进制,再在jstack输出中搜索nid=0x...,看它在执行什么(常见于未关闭的线程池、递归创建线程、监听器反复注册) - 统计线程状态:
jstack对比预期线程数;若 WAITING 线程远超正常值,可能是线程池阻塞或连接池泄漏连带引发线程堆积| grep 'java.lang.Thread.State' | wc -l
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











