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

1、問題起因

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

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
  • MaxProcessMemory 指的是一個進程的最大內存
  • JVMMemory JVM內存
  • ReservedOsMemory 保留的操作系統內存
  • ThreadStackSize 線程棧的大小

在java語言裏, 當你創建一個線程的時候,虛擬機會在JVM內存創建一個Thread對象同時創建一個操作系統線程,而這個系統線程的內存用的不是JVMMemory,而是系統中剩下的內存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
由公式得出結論:你給JVM內存越多,那麼你能創建的線程越少,越容易發生java.lang.OutOfMemoryError: unable to create new native thread。

2、解決問題

1、如果程序中有bug,導致創建大量不需要的線程或者線程沒有及時回收,那麼必須解決這個bug,修改參數是不能解決問題的。
2、如果程序確實需要大量的線程,現有的設置不能達到要求,那麼可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個因素,來增加能創建的線程數:

  • MaxProcessMemory 使用64位操作系統
    MaxProcessMemory進程最大的尋址空間,但我想這個值應該也不會超過虛擬內存和物理內存的總和吧。關於不同系統的進程可尋址的最大空間,可參考下面表格:
    這裏寫圖片描述

    JVMMemory: Heap + PermGen

    ReservedOSMemory:Native heap,JNI

    在2000/XP/2003的boot.ini裏頭有一個啓動選項,好像是:/PAE /3G ,可以讓用戶進程最大內存擴充至3G,這時操作系統只能佔用最多1G的虛存。那樣應該可以讓JVM創建更多的線程。

  • JVMMemory 減少JVMMemory的分配 使用tomcat的catalina.bat這裏配置,下面有解析。

-Xms1024m 
-Xmx1024m 
-XX:PermSize=256M 
-XX:MaxNewSize=512m 
-XX:MaxPermSize=256m 
-XX:SurvivorRatio=6
  • ThreadStackSize 減小單個線程的棧大小

    -Xss(或-ss) 這個其實也是可以默認的,如果你真的覺得有設置的必要,你就改下吧,1.5以後是1M的默認大小(指一個線程的native空間),如果代碼不多,可以設置小點來讓系統可以接受更大的內存。注意,還有一個參數是-XX:ThreadStackSize,這兩個參數在設置的過程中如果都設置是有衝突的,一般按照JVM常理來說,誰設置在後面,就以誰爲主,但是最後發現如果是在1.6以上的版本,-Xss設置在後面的確都是以-Xss爲主,但是要是-XX:ThreadStackSize設置在後面,主線程還是爲-Xss爲主,而其它線程以-XX:ThreadStackSize爲主,主線程做了一個特殊判定處理;單獨設置都是以本身爲主,-Xss不設置也不會採用其默認值,除非兩個都不設置會採用-Xss的默認值。

發佈了146 篇原創文章 · 獲贊 130 · 訪問量 78萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章