OutOfMemoryError系列(5): Unable to create new native thread

这是本系列的第五篇文章, 相关文章列表:

Java程序本质上是多线程的, 可以同时执行多项任务。 类似于在播放视频的时候, 可以拖放窗口中的内容, 却不需要暂停视频播放, 即便是物理机上只有一个CPU。

线程(thread)可以看作是干活的工人(workers)。 如果只有一个工人, 在同一时间就只能执行一项任务. 假若有很多工人, 那么就可以同时执行多项任务。

和现实世界类似, JVM中的线程也需要内存空间来执行自己的任务. 如果线程数量太多, 就会引入新的问题:

java-lang-outofmemoryerror-unable-to-create-new-native-thread

java.lang.OutOfMemoryError: Unable to create new native thread 错误表达的意思是: 程序创建的线程数量已达到上限值

原因分析

JVM向操作系统申请创建新的 native thread(原生线程)时, 就有可能会碰到 java.lang.OutOfMemoryError: Unable to create new native thread 错误. 如果底层操作系统创建新的 native thread 失败, JVM就会抛出相应的OutOfMemoryError. 原生线程的数量受到具体环境的限制, 通过一些测试用例可以找出这些限制, 请参考下文的示例. 但总体来说, 导致 java.lang.OutOfMemoryError: Unable to create new native thread 错误的场景大多经历以下这些阶段:

  1. Java程序向JVM请求创建一个新的Java线程;

  2. JVM本地代码(native code)代理该请求, 尝试创建一个操作系统级别的 native thread(原生线程);

  3. 操作系统尝试创建一个新的native thread, 需要同时分配一些内存给该线程;

  4. 如果操作系统的虚拟内存已耗尽, 或者是受到32位进程的地址空间限制(约2-4GB), OS就会拒绝本地内存分配;

  5. JVM抛出 java.lang.OutOfMemoryError: Unable to create new native thread 错误。

示例

下面的代码在一个死循环中创建并启动很多新线程。代码执行后, 很快就会达到操作系统的限制, 报出 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-bit Mac OS X 10.9, Java 1.7.0_45 – JVM 在创建 #2031 号线程之后挂掉
  • 64-bit Ubuntu Linux, Java 1.7.0_45 – JVM 在创建 #31893 号线程之后挂掉
  • 64-bit Windows 7, Java 1.7.0_45 – 由于操作系统使用了不一样的线程模型, 这个错误信息似乎不会出现. 创建 #250,000 号线程之后,Java进程依然存在, 但虚拟内存(swap file) 的使用量达到了 10GB, 系统运行极其缓慢,基本上没法运行了。

所以如果想知道系统的极限在哪儿, 只需要一个小小的测试用例就够了, 找到触发 java.lang.OutOfMemoryError: Unable to create new native thread 时创建的线程数量即可。

解决方案

有时可以修改系统限制来避开 Unable to create new native thread 问题. 假如JVM受到用户空间(user space)文件数量的限制, 像下面这样,就应该想办法增大这个值:

[root@dev ~]# ulimit -a
core file size          (blocks, -c) 0
...... 省略部分内容 ......
max user processes              (-u) 1800

更多的情况, 触发创建 native 线程时的OutOfMemoryError, 表明编程存在BUG. 比如, 程序创建了成千上万的线程, 很可能就是某些地方出大问题了 —— 没有几个程序可以 Hold 住上万个线程的。

一种解决办法是执行线程转储(thread dump) 来分析具体情况。 一般需要花费好几个工作日来处理。 当然, 我们推荐使用 Plumbr 来找出问题的根源, 分分钟帮你搞定。

原文链接: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

翻译日期: 2017年9月21日

翻译人员: 铁锚: http://blog.csdn.net/renfufei

阅读更多

求助求助:unable to create new native thread

06-28

有一段服务器代码,特点是线程创建多,数据库查询多。 rn在我本地机器上跑没有问题,在客户机器上跑就会出java.long.OutOfMemoryErr: unable to create new native thread。出现的地方很多,比如线程start,通过newInstance创建对象,创建数据库连接。 rnrn通过不停创建线程测试,在我本地可以创建4000多个线程,可是在客户机器上可以创建的线程数量不超过40。 rn测试代码: rnpackage test; rnpublic class Test implements Runnable rn rn private static Object waitObj = new Object(); rn rn private int threadNo; rn rn public Test(int aNo) rn super(); rn threadNo = aNo; rn rn rn public static void main(String[] args) rn rn int iNo = 1; rn while(true) rn Test t = new Test(iNo); rn Thread th = new Thread(t); rn th.start(); rn try rn Thread.sleep(10); rn catch (InterruptedException e) rn break; rn rn iNo ++; rn rn waitObj.notifyAll(); rn rn rn public void run() rn System.out.println("Thread " + threadNo + " created."); rn synchronized(waitObj) rn try rn waitObj.wait(); rn catch (InterruptedException e) rn System.err.println("InterruptedException at Thread " + threadNo + "."); rn rn rn System.out.println("Thread " + threadNo + " finished."); rn rn rnrnpackage test;rnpublic class Test implements Runnablern rn private static Object waitObj = new Object();rnrn private int threadNo;rnrn public Test(int aNo) rn super();rn threadNo = aNo;rn rnrn public static void main(String[] args) rnrn int iNo = 1;rn while(true)rn Test t = new Test(iNo);rn Thread th = new Thread(t);rn th.start();rn try rn Thread.sleep(10);rn catch (InterruptedException e) rn break;rn rn iNo ++;rn rn waitObj.notifyAll();rn rnrn public void run() rn System.out.println("Thread " + threadNo + " created.");rn synchronized(waitObj)rn try rn waitObj.wait();rn catch (InterruptedException e) rn System.err.println("InterruptedException at Thread " + threadNo + ".");rn rn rn System.out.println("Thread " + threadNo + " finished.");rn rnrnrn本地机器和客户机器装的jdk版本是同样的。 rnrn看过http://jroller.com/rreyelts/date/20040909 rn意思大概是说分配个虚拟机的内存越多,可以创建的线程数量就越少。 rn通过java -Xmx1000M test.Test这样,在本地上可以看出来变化效果,但是在客户机器上看不出来有任何变化。 rnrn客户机器输出: rnjava test.Test rnThread 1 created. rnThread 2 created. rnThread 3 created. rnThread 4 created. rnThread 5 created. rnThread 6 created. rnThread 7 created. rnThread 8 created. rnThread 9 created. rnThread 10 created. rnThread 11 created. rnThread 12 created. rnThread 13 created. rnThread 14 created. rnThread 15 created. rnThread 16 created. rnThread 17 created. rnThread 18 created. rnThread 19 created. rnThread 20 created. rnThread 21 created. rnThread 22 created. rnThread 23 created. rnThread 24 created. rnThread 25 created. rnThread 26 created. rnThread 27 created. rnThread 28 created. rnThread 29 created. rnThread 30 created. rnThread 31 created. rnThread 32 created. rnThread 33 created. rnThread 34 created. rnThread 35 created. rnThread 36 created. rnException in thread "main" java.lang.OutOfMemoryError: unable to create new native thread rn at java.lang.Thread.start0(Native Method) rn at java.lang.Thread.start(Unknown Source) rn at test.Test.main(Test.java:29) rnrn机器配置: rn 本地:intel pentium dual E2160 @ 1.80G 1.79G, 1.99G内存 rn 客户机器:AMD xxxx rnrn都快困扰死我了。 rnrn就15分了,以后又分一定补上。 rnQQ:84403389 rnEmail:zyongsheng83@163.com rn等。谢谢。 rn

没有更多推荐了,返回首页