问题描述

最近连续两天大约凌晨3点,线上服务开始异常,出现OOM报错。且服务所在的物理机只能ping通,但是无法登录。报错信息如下:

ERROR 04-12 03:01:43,930 [DefaultQuartzScheduler_Worker-3] JobRunShell[JobRunShell]:211 Job threw an unhandled Exception:
java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
at java.util.concurrent.ForkJoinPool.createWorker(ForkJoinPool.java:1483)
...
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

排查过程

根据日志OOM报错,怀疑是内存不足或内存泄露的原因,需要查看内存的使用情况。考虑到JConsoleVisualVM具有可视化界面,能看出历史变化趋势,更直观地排查问题,因此为程序配置了jmx参数。重启应用,使用VisualVM连接应用的jmx端口。应用配置jmx端口的参数如下:

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false  -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=9998

VisualVM显示使用的内存是正常的,没有持续飙升。但是线程数却比较异常,随时间推移在持续增加。因此考虑看看是什么线程在持续增加,jstack是一个比较好用的工具,它用于生成 JAVA 虚拟机当前时刻的线程快照。

使用jstack -F PID打印出了所有线程,发现有大片下面的堆栈信息。注意到com.xxx.http.IdleConnectionMonitorThread.run() @bci=15, line=22 (Compiled frame)方法出现的特别多。

Thread 7760: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
- java.util.concurrent.ForkJoinPool.awaitWork(java.util.concurrent.ForkJoinPool$WorkQueue, int) @bci=354, line=1821 (Compiled frame)
- java.util.concurrent.ForkJoinPool.runWorker(java.util.concurrent.ForkJoinPool$WorkQueue) @bci=44, line=1690 (Compiled frame)
- java.util.concurrent.ForkJoinWorkerThread.run() @bci=24, line=157 (Compiled frame) Thread 7759: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- com.xxx.http.IdleConnectionMonitorThread.run() @bci=15, line=22 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=745 (Compiled frame) Thread 7758: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- com.xxx.http.IdleConnectionMonitorThread.run() @bci=15, line=22 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=745 (Compiled frame)

在项目搜索类IdleConnectionMonitorThread,并查看22行内容。发现如果不执行shutdown()方法,那么该后台线程会持续地执行wait()方法,导致该线程不退出。实际情况是确实没有执行shutdown()方法,随着每10分钟执行一次计算任务,每次计算任务会执行一批http请求,每个http请求就会创建出一个后台线程,这样会导致线程数越来越多。

联系了sdk的提供方,提供了后台进程的停止方法。在程序请求http完成后,释放请求的资源,停止了后台线程。使用VisualVm观察了一段时间,发现线程数不在增长了,未出现OOM报错。至此问题解决。

虽然问题解决了,不过还有个疑问,线程数达到多少会触发unable to create new native thread报错。查阅博客了解到,一个进程最多能创建多少线程是受多因素影响的,基本上是系统支持的最大PID、用户可创建最大线程数、系统支持的最大线程数的最小值。通过查看服务器配置,系统支持的最大PID的值是最小的:32768,也就是说一个进程最多创建大约3w个线程。由于服务器上部署了线上服务,不方便在复现验证创建多少个线程时出现OOM报错。

java.lang.OutOfMemoryError: unable to create new native thread问题排查以及当前系统最大进程数量

一个JVM可以创建多少线程,首先由JVM设置决定(-Xms,-Xmx,-Xss),另外受到外部因素影响,就是系统设置(最大PID、最大线程、栈内存大小、最重要的还是物理内存由多少)、其二就是用户设置(用户可以运行多少个进程或线程),综合上述因素的最小值就是一个JVM可以创建多少线程。

系统支持的最大进程数
cat /proc/sys/kernel/pid_max
32768 系统支持的最大线程数
cat /proc/sys/kernel/threads-max
513024 进程可用最大虚拟内存
ulimit -v
unlimited 最大栈大小
ulimit -s
8192 每个用户可创建最大进程数
ulimit -u
256512

总结

1.JConsoleVisualVM具有可视化界面,可以方便地查看CPU占用、内存使用、类数量、线程数的历史变化趋势。

2.jstack命令可以查看正在运行的程序当前时刻的所有线程信息。

3.一个进程最多能创建多少线程,是受多因素影响的,基本上是系统支持的最大PID、用户可创建最大线程数、系统支持的最大线程数的最小值。

参考资料

java.lang.OutOfMemoryError- unable to create new native thread 问题排查的更多相关文章

  1. java.lang.OutOfMemoryError: unable to create new native thread问题排查以及当前系统最大进程数量

    1. 问题描述 线上某应用出问题,查看日志 这一组服务器是2台,每台都有.配置为64G,使用7G,空余内存非常多 2. 问题排查 环境变化:程序迁移到新机器,新机器是CentOS 7,程序运行账号由原 ...

  2. java.lang.OutOfMemoryError: unable to create new native thread如何解决

    工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题.分析问题.解决问题. 一.认识问题: 首先我们通过下面这个 测试程序 来认识这个问题:运行的环境 ( ...

  3. JVM内存越多,能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。

    一.认识问题: 首先我们通过下面这个 测试程序 来认识这个问题:运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse ...

  4. spark java.lang.OutOfMemoryError: unable to create new native thread

    最近迁移集群,在hadoop-2.8.4 的yarn上跑 spark 程序 报了以下错误 java.lang.OutOfMemoryError: unable to create new native ...

  5. 剥下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 创建线程数公式(MaxProcessMemory - JVMMemory – ReservedOsMemory)

    剥下“java.lang.OutOfMemoryError: unable to create new native thread”的外衣 星期一早上到了公司,据称产品环境抛出了最可爱的异常—OutO ...

  6. 解决java.lang.OutOfMemoryError: unable to create new native thread问题

    解决:1.升级JVM到最新的版本 最新版本的JVM一般在内存优化方面做的更好,升级JVM到最新的版本可能会缓解测问题2.从操作系统层面去解决 使用64位操作系统 如果使用32位操作系统遇到unable ...

  7. 关于“java.lang.OutOfMemoryError : unable to create new native Thread”的报错问题

    好吧 我发誓这是postgresql的Mirroring Controller的RT测试的最后一个坑了. 在这个RT测试的最后,要求测试Mirroring Controller功能在长时间运行下的稳定 ...

  8. 记一次内存溢出java.lang.OutOfMemoryError: unable to create new native thread

    一.问题: 春节将至,系统访问量进入高峰期.随之系统出现了异常:java.lang.OutOfMemoryError: unable to create new native thread.在解决这个 ...

  9. [java] [error] java.lang.OutOfMemoryError: unable to create new native thread

    前言 最近公司的服务器出现了oom的报错,经过一番排查,终于找到了原因.写下这篇博客是为了记录下查找的过程,也是为了帮助那些跟我门遇到的情况相同的人可以更快的寻找到答案. 环境 系统:linux(ce ...

  10. spark大批量读取Hbase时出现java.lang.OutOfMemoryError: unable to create new native thread

    这个问题我去网上搜索了一下,发现了很多的解决方案都是增加的nproc数量,即用户最大线程数的数量,但我修改了并没有解决问题,最终是通过修改hadoop集群的最大线程数解决问题的. 并且网络上的回答多数 ...

随机推荐

  1. Buuoj 被嗅探的流量

    Buuoj 被嗅探的流量 这个点进去之后看到了很像flag的内容 这个好像就是 也可以右键Analyse→Follow→TCP Stream或HTTP stream

  2. Hadoop之HDFS优缺点、设计原理、框架

    如需大数据开发整套视频(hadoop\hive\hbase\flume\sqoop\kafka\zookeeper\presto\spark):请联系QQ:1974983704  Hadoop的前世今 ...

  3. JS实现10进制和26进制的转换

    转载:https://blog.csdn.net/quentain/article/details/52803891 //将26进制转10进制 var ConvertNum = function (s ...

  4. JSTL练习

    求:request 域中有一个存有 user 对象的 ist 集合.需要使用 jstltel 将 list 集合故据展示到 jsp 页面的表格 table表格中 List list = new Arr ...

  5. Net异步委托-泛型委托Action<T>与Func<T,TResult>及 异步调用AsyncCallback

    1.相同点 Func<ReqMode,ResultModel> 与 Action<ReqMode> 1).都是Net3.5 之后内置的委托方法,作用几乎一致 2).都支持lam ...

  6. [复现]陇原战"疫"2021网络安全大赛-PWN

    bbbaby 控制__stack_chk_fail,栈溢出 from pwn import * context.os = 'linux' context.log_level = "debug ...

  7. C# Set集合

    包含不重复元素的集合称为"集(set)"..NET Framework包含两个集HashSet<T>和SortedSet<T>,它们都实现ISet<T ...

  8. 1.3 ODBC 部署监控数据库

    一.安装ODBC 来自为知笔记(Wiz)

  9. ASP.NET Core - 配置系统之自定义配置提供程序

    4. 自定义配置提供程序 在 .NET Core 配置系统中封装一个配置提供程序关键在于提供相应的 IconfigurationSource 实现和 IConfigurationProvider 接口 ...

  10. Python学习笔记--第二阶段啦

    初识对象 示例: 类的成员方法 上图中的self必须填写!!! 示例: 类和对象 有c和c++语言基础的话,就会发现其实是一样的道理,只是实现代码有差异 构造方法(init) 示例: 注意: 其他内置 ...