美文网首页
常见OOM问题之无法创建新的本地线程问题详解

常见OOM问题之无法创建新的本地线程问题详解

作者: HeapDump性能社区 | 来源:发表于2022-09-07 13:39 被阅读0次

    本文来自于HeapDump性能社区! !有性能问题,上HeapDump性能社区!
    正文:

    Java 应用程序本质上是多线程的。这意味着用 Java 编写的程序可以同时(表面上)做几件事。例如——即使在只有一个处理器的机器上——当您将内容从一个窗口拖到另一个窗口时,在后台播放的电影不会因为您一次执行多项操作而停止。

    考虑线程的一种方法是将它们视为可以向其提交任务以执行的工人。如果您只有一名工人,他或她当时只能执行一项任务。但是,当您拥有十几个工人时,他们可以同时执行您的多个命令。

    现在,与物理世界中的工人一样,JVM 中的线程需要一些肘部空间来执行他们被召唤来处理的工作。当线程多于内存空间时,我们已经为问题奠定了基础:

    v2-6f8d4aaeebe7a371948b0325ebfbd1e7_1440w.png

    消息java.lang.OutOfMemoryError: Unable to create new native thread意味着Java 应用程序已达到它可以启动的线程数限制。

    1,什么原因造成的?

    您有机会遇到java.lang.OutOfMemoryError: Unable to create new native thread每当 JVM 向操作系统请求新线程时。每当底层操作系统无法分配新的本机线程时,就会抛出此 OutOfMemoryError。本机线程的确切限制非常依赖于平台,因此我们建议通过运行类似于以下示例的测试来找出这些限制。但是,一般情况下,导致java.lang.OutOfMemoryError: Unable to create new native thread 的情况会经历以下几个阶段:

    1. 运行在 JVM 中的应用程序请求一个新的 Java 线程
    2. JVM 本机代码将创建新本机线程的请求代理到操作系统
    3. 操作系统尝试创建一个新的本地线程,该线程需要为线程分配内存
    4. 操作系统将拒绝本机内存分配,因为 32 位 Java 进程大小已耗尽其内存地址空间 - 例如 (2-4) GB 进程大小限制已达到 - 或操作系统的虚拟内存已完全耗尽
    5. java.lang.OutOfMemoryError:无法创建新的本地线程引发错误。

    2,举个例子

    以下示例在循环中创建并启动新线程。运行代码时,会快速达到操作系统限制并显示java.lang.OutOfMemoryError: Unable to create new native thread消息。

    while(true){
        new Thread(new Runnable(){
            public void run() {
                try {
                    Thread.sleep(10000000);
                } catch(InterruptedException e) { }        
            }    
        }).start();
    }
    

    确切的本机线程限制取决于平台,例如在 Windows、Linux 和 Mac OS X 上的测试表明:

    • 64 位 Mac OS X 10.9,Java 1.7.0_45 – JVM 在 #2031 线程创建后终止
    • 64 位 Ubuntu Linux,Java 1.7.0_45 – JVM 在 #31893 线程创建后终止
    • 64 位 Windows 7、Java 1.7.0_45 – 由于操作系统使用的线程模型不同,此错误似乎不会在此特定平台上引发。在线程 #250,000 上,即使交换文件已增长到 10GB 并且应用程序面临极端的性能问题,该进程仍处于活动状态。

    因此,请确保通过调用一个小测试了解自己的限制,并找出何时会触发java.lang.OutOfMemoryError: Unable to create new native thread

    3,解决方案

    有时,您可以通过增加操作系统级别的限制来绕过无法创建新的本机线程问题。例如,如果您限制了 JVM 可以在用户空间中产生的进程数,您应该检查并可能增加限制:

    [root@dev ~]# ulimit -a
    核心文件大小(块,-c)0
    --- 为简洁起见 ---
    最大用户进程 (-u) 1800
    

    通常情况下,OutOfMemoryError 对新本地线程的限制表明存在编程错误。当您的应用程序产生数千个线程时,很可能出现了严重错误——没有多少应用程序可以从如此大量的线程中受益。

    解决问题的一种方法是开始进行线程转储以了解情况。你通常会花几天的时间来做这件事。我们的建议是将Plumbr连接到您的应用程序,以找出导致问题的原因以及如何在几分钟内解决它。

    Java OOM系列专题:

    第一篇:Java OOM 原理篇 : 什么是 Java OOM

    第二篇:Java OOM 基础篇:常见的OutOfMemoryError 场景一:Java heap space 堆溢出问题详解

    第三篇:Java OOM 基础篇:常见的OutOfMemoryError 场景二 : GC overhead limit exceeded 问题详解

    第四篇:Java OOM 基础篇:常见的OutOfMemoryError 场景三: PermGen space 永久空间问题详解

    第五篇:Java OOM 基础篇:常见的OutOfMemoryError 场景四: Permgen size 元空间问题详解

    第六篇:Java OOM 实战篇:应用故障之Java heap space 堆溢出实战

    第七篇:Java OOM 高级篇:体验了一把线上CPU100%及应用OOM的排查和解决过程

    第八篇:Java OOM 高级篇:线上Docker 上Springboot程序OOM问题的排查分享

    相关文章

      网友评论

          本文标题:常见OOM问题之无法创建新的本地线程问题详解

          本文链接:https://www.haomeiwen.com/subject/aqjgnrtx.html