=============================================================================================================================
最近部署一个新的服务到两台服务器上,之前这两台服务器上已经部署了两个服务,但在部署完一段时间后出现了线上异常报错的情况,具体信息如上图。
分析原因
思考线程的一种方法是将它们视为可供提交任务的工作人员。如果你只有一名员工,他/她只能同时做一个任务,但是当你有一打员工供你差遣,他们可以同时完成你的几个要求。
现在, 就像在现实世界的员工,在JVM里的线程也需要一些空间来开展他们被传唤去要处理的工作。当线程数超过了这个内存空间的限制的时候,我们就会碰到下边的问题:
==========================================================================================================================
可能的原因
OutOfMemoryError: unable to create new native thread出现的情况有两种:
1. 服务器剩余内存不足(非JVM内存),不能创建新的线程
能创建的线程数的具体计算公式如下:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一个进程的最大内存
JVMMemory JVM内存
ReservedOsMemory 保留的操作系统内存
ThreadStackSize 线程栈的大小
2. 超出服务器用户最大进程限制:
通过以下命令可以查看(注意,不同用户,最大进程限制配置可能不一样):
ulimit -u
分析:
通过检查jvm参数,发现没有设置-Xss,使用的默认大小,其次,使用free -m查看服务器可用内存,发现还有很多剩余,怀疑是超出服务器用户最大进程限制,所以应该是第二种情况造成的异常。
只要JVM向OS申请新线程,你都有机会碰到java.lang.OutOfMemoryError: Unable to create new native thread。只要下面的OS不能再分配一个新的native thread,这个OutOfMemoryError会被抛出。准确的native thread限制与对应的平台有关, 通常引发java.lang.OutOfMemoryError:Unable to create new native thread会经过下列阶段:
1. 运行在JVM里的一个应用请求一个新的Java线程
2. JVM native代码传递要创建一个新的native 线程到OS
3. OS尝试创建一个新的native 线程, 同时需要分配内存给这个线程
4. OS将会拒绝本地内存分配, 可能是因为32-bit Java进程大小已经耗尽了它的内存地址区域,如: 达到了2-4GB的进程大小限制,或是这个OS的虚拟内存已经被耗尽
5. 抛出java.lang.OutOfMemoryError: Unable to create new native thread错误
事后模拟:
1.在java工程中定义一个http接口,当调用时,不停的创建和启动线程。
@GetMapping("/testThread")
public void testThread() { List<Thread> list = new ArrayList<>(); while(true) { Thread t = new Thread(() -> { try { Thread.sleep(600000L); }catch (InterruptedException e){ log.error("###",e); } }); t.start(); list.add(t); log.info(String.valueOf(list.size())); }}
2.设置服务器java用户的最大进程数量为1000个
==========================================================================================================================
修复
在文件/etc/security/limits.d/20-nproc.conf调整用户的最大进程数
有时候,你可以通过增加OS层面的限制来绕过这个Unable to create new native thread问题。例如, 如果你限制了JVM在 user space可以生成的max user processes, 那么你应该检查并尝试增大这个限制:
通常情况下,因为本机达到线程的限制而抛出OutOfMemoryError错误提示可能表明有编程错误。当你的应用生成了上千个线程, 很有可能有些地方出了大问题, 没有太多的应用程序可以从如此大量的线程中获益(线程过多, 过犹不及)。
欢迎收藏、关注、点赞三连哦。