java.lang.OutOfMemoryError:unabletocreatenewnativethread(轉)

developerguy發表於2014-10-04

解決 – java.lang.OutOfMemoryError: unable to create new native thread

工作中碰到過這個問題好幾次了,覺得有必要總結一下,所以有了這篇文章,這篇文章分為三個部分:認識問題、分析問題、解決問題。 

一、認識問題: 

首先我們通過下面這個 測試程式 來認識這個問題:

執行的環境 (有必要說明一下,不同環境會有不同的結果):32位 Windows XP, 1.5.0_22, myeclipse 6.6,

測試程式: 

Java程式碼 

import java.util.concurrent.CountDownLatch;   

public class TestNativeOutOfMemoryError {   

    public static void main(String[] args) {   

        for (int i = 0;; i++) {   

            System.out.println(“i = ” + i);   

            new Thread(new HoldThread()).start();   

        }   

    }   

}   

 

class HoldThread extends Thread {   

    CountDownLatch cdl = new CountDownLatch(1);   

 

    public HoldThread() {   

        this.setDaemon(true);   

    }   

    public void run() {   

        try {   

            cdl.await();   

        } catch (InterruptedException e) {   

        }   

    }   

}  

import java.util.concurrent.CountDownLatch;

public class TestNativeOutOfMemoryError {

public static void main(String[] args) {

  for (int i = 0;; i++) {

   System.out.println(“i = ” + i);

   new Thread(new HoldThread()).start();

  }

}

}

class HoldThread extends Thread {

CountDownLatch cdl = new CountDownLatch(1);

public HoldThread() {

  this.setDaemon(true);

}

public void run() {

  try {

   cdl.await();

  } catch (InterruptedException e) {

  }

}

}  

 

不指定任何JVM引數,eclipse中直接執行輸出,看到了這位朋友了吧:

Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread

    at java.lang.Thread.start0(Native Method)

    at java.lang.Thread.start(Thread.java:597)

    at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:20) 

 

二、分析問題: 

這個異常問題本質原因是我們建立了太多的執行緒,而能建立的執行緒數是有限制的,導致了異常的發生。能建立的執行緒數的具體計算公式如下: 

(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads 

MaxProcessMemory 指的是一個程式的最大記憶體

JVMMemory         JVM記憶體

ReservedOsMemory  保留的作業系統記憶體

ThreadStackSize      執行緒棧的大小

在java語言裡, 當你建立一個執行緒的時候,虛擬機器會在JVM記憶體建立一個Thread物件同時建立一個作業系統執行緒,而這個系統執行緒的記憶體用的不是JVMMemory,而是系統中剩下的記憶體(MaxProcessMemory – JVMMemory – ReservedOsMemory)。 

 

結合上面例子我們來對公式說明一下: 

MaxProcessMemory 在32位的 windows下是 2G

JVMMemory   eclipse預設啟動的程式記憶體是64M

ReservedOsMemory  一般是150M左右

ThreadStackSize 32位 JDK 1.5預設的stacksize 256K左右

公式如下:

(2*1024*1024-64*1024-150*1024)/256 = 7336 

公式計算所得7336,和實踐7117基本一致(有偏差是因為ReservedOsMemory不能很精確) 

由公式得出結論:你給JVM記憶體越多,那麼你能建立的執行緒越少,越容易發生java.lang.OutOfMemoryError: unable to create new native thread。 

咦,有點揹我們的常理,恩,讓我們來驗證一下,依舊使用上面的測試程式,加上下面的JVM引數,測試結果如下: 

ThreadStackSize      JVMMemory                    能建立的執行緒數

預設的256K             -Xms64m -Xmx64m    i = 7117

預設的256K             -Xms32m -Xmx32m    i = 7244

-Xss128k             -Xms64m -Xmx64m    i = ? 

完全和公式一致。 

三、解決問題: 

1, 如果程式中有bug,導致建立大量不需要的執行緒或者執行緒沒有及時回收,那麼必須解決這個bug,修改引數是不能解決問題的。

2, 如果程式確實需要大量的執行緒,現有的設定不能達到要求,那麼可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個因素,來增加能建立的執行緒數:

a, MaxProcessMemory 使用64位作業系統

b, JVMMemory   減少JVMMemory的分配

c, ThreadStackSize  減小單個執行緒的棧大小

http://blog.csdn.net/kesay/article/details/5728810

 


相關文章