应优先排查linux三层线程限制:ulimit -u(用户级)、/proc/sys/kernel/threads-max(内核级)、/proc/sys/kernel/pid_max(pid池上限),任一层触顶均导致“unable to create new native thread”错误,堆内存充足时勿盲目调jvm参数。

查清到底是哪一层在卡线程创建
Java 或 Go 应用报 java.lang.OutOfMemoryError: unable to create new native thread,但堆内存充足,别急着调 JVM 参数——90% 是 Linux 三层限制中某一层悄悄触顶:ulimit -u(用户级)、/proc/sys/kernel/threads-max(内核级)、/proc/sys/kernel/pid_max(PID 池上限)。任一层满,都会失败。
快速定位方法:
-
ps -eLf | wc -l查当前总线程数 -
ulimit -u看当前 shell 的用户级上限(普通用户常为 1024) -
cat /proc/sys/kernel/threads-max和cat /proc/sys/kernel/pid_max对比上面结果,看是否接近 -
prlimit -n $PID查具体进程实际继承的nproc值(注意:systemd 服务默认不读limits.conf)
优先改 ulimit -u(最常见生效点)
绝大多数 Java、Python 多线程服务卡在这层,因为 Linux 中线程即轻量进程,ulimit -u 同时约束该用户所有进程 + 线程总数,且 Java 进程启动时直接继承 shell 的该限制。
临时生效(当前终端及子进程):ulimit -u 65535
永久生效(需新登录会话):
- 编辑
/etc/security/limits.d/90-nproc.conf,写入:* soft nproc 65535 * hard nproc 65535
-
root用户也要单独配:root soft nproc 65535和root hard nproc 65535,否则 SSH 登录后仍可能受限 - 确认
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/system-auth(RHEL/CentOS)含session required pam_limits.so
systemd 服务不走 PAM limits 流程,必须额外配置:
- 在
/etc/systemd/system/myservice.service的[Service]段加:LimitNPROC=65535 - 或全局设:
DefaultLimitNPROC=65535在/etc/systemd/system.conf,再执行sudo systemctl daemon-reload
改 /proc/sys/kernel/threads-max 要同步检查 pid_max
这个值是内核能支撑的全局线程总数,不是 per-user,也不是 per-cgroup。默认 ≈ mem_total_kb / (4 * page_size),物理内存越大初始值越高,但受 pid_max 硬性约束——如果 threads-max > pid_max,写入会静默截断并报 Invalid argument。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
临时修改(重启失效):
sudo sysctl -w kernel.threads-max=2097152- 或:
echo 2097152 | sudo tee /proc/sys/kernel/threads-max
永久生效:
- 写入
/etc/sysctl.d/99-thread-limit.conf:kernel.threads-max = 2097152 - 执行
sudo sysctl --system - RHEL/CentOS 7+ 还需
sudo systemctl restart systemd-sysctl
务必先验证:cat /proc/sys/kernel/pid_max ≥ 目标 threads-max 值,否则改了也白改。
别漏掉 pid_max(系统级 PID 池天花板)
它不是直接限制线程数,但它是所有进程/线程分配 PID 的池子。当 ulimit -u 和 threads-max 都调高了,却还是 fork: Cannot allocate memory,大概率是它没跟上。
临时调高:sudo sysctl -w kernel.pid_max=4194304
永久配置:
- 在
/etc/sysctl.conf或/etc/sysctl.d/99-pid-limit.conf加:kernel.pid_max = 4194304 - 执行
sudo sysctl --system
x86_64 架构理论上限约 4194304,设太高无意义,反而可能增加调度开销;设太低则会导致 Resource temporarily unavailable 错误,即使其他两层都宽松。










