Redhat虚拟机内存充足但频繁出现OOM问题求助
Redhat虚拟机内存充足但频繁出现OOM问题求助
兄弟,你遇到的这个问题我之前帮好几个团队排查过,核心不是物理内存不够,而是你的Java进程碰到了系统层面的线程数量限制!
先给你拆解下关键信息:你贴的错误是Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread,这个和咱们常说的“堆内存不足(Java heap space)”完全不是一回事——它指的是Java虚拟机没法向操作系统申请创建新的本地线程了,哪怕你还有大把物理内存闲置着。
结合你的场景分析下原因:
- 你没给Java进程设置
Xmx等参数,JVM会用默认堆大小,但更关键的是每个Java线程都需要占用一定的本地内存(用来存储线程栈、寄存器等数据),而且系统对「单个进程能创建的线程数」「整个系统的总线程数」都有严格限制,这些限制和物理内存大小不是直接挂钩的。 - 你的监控只看系统总剩余内存,完全没关注线程资源的使用情况,这就导致你误判了问题根源;而多个进程同时失败,说明是系统全局的线程资源耗尽了,不是单个进程的代码问题——毕竟那些出问题的进程平时都稳定运行,没有突发流量。
给你一套具体的排查和解决步骤:
- 先查系统线程限制
- 查看系统全局的总线程数上限:执行
sysctl kernel.threads-max,这个数值是系统能承载的所有线程总数。 - 查看当前用户的进程线程数上限:执行
ulimit -u(每个线程在系统里属于轻量级进程,这个限制是单用户能创建的进程/线程总数),也可以去/etc/security/limits.conf里看nproc的配置。 - 实时统计当前系统已用线程数:执行
ps -eLf | wc -l,如果这个数值接近kernel.threads-max,那就是全局线程资源耗尽了。
- 查看系统全局的总线程数上限:执行
- 排查Java进程的线程使用
- 找到报错的Java进程PID,用
jstack <PID>导出线程栈,看看里面到底有多少线程——很多没优化的Java程序会无意识创建大量线程(比如线程池没设上限、异步任务没管控)。 - 也可以用
top -H -p <PID>直接查看该进程下的线程数量,直观又方便。
- 找到报错的Java进程PID,用
- 针对性调整解决
- 如果是系统全局线程数不够:临时调整可以用
sysctl -w kernel.threads-max=65535(数值根据你的服务器情况调整,别太夸张),要永久生效就修改/etc/sysctl.conf后执行sysctl -p。 - 如果是用户级线程限制:在
/etc/security/limits.conf里添加两行配置:* soft nproc 65535和* hard nproc 65535,之后重启相关服务或者让用户重新登录生效。 - 优化Java进程:给Java进程加上
-Xss参数调小线程栈大小(比如-Xss256k,默认一般是1M,调小后每个线程占用的本地内存更少,就能创建更多线程);同时给进程设置合理的Xmx/Xms参数,避免堆内存无限制占用间接挤压本地内存空间;还要检查代码里的线程池、异步逻辑,有没有线程泄漏或者不合理的线程创建。
- 如果是系统全局线程数不够:临时调整可以用
- 补全监控维度
- 以后一定要加上进程级监控:比如每个Java进程的线程数、堆/非堆内存使用量;还要监控系统总线程数、用户级线程使用量,这样下次出问题就能直接定位根源,不用再走弯路了。
备注:内容来源于stack exchange,提问作者MikeKulls
相关产品推荐
相关产品推荐

