問題:
數據源連接池線程數最大連接數最初設置300,但是一周有2-3次發生活躍連接數超過最大線程數,導致線程堵塞,服務查詢等待超時,所以運維將最大線程數調至1500,這樣導致JVM創建的線程數大大增多,原先配置的JVM內存不夠使用,導致內存溢出,無法創建線程。
解決:
后將最大線程數調至1024,保證不會超過JVM內存限制。
系統能創建的線程數的計算公式如下:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一個進程的最大內存
JVMMemory JVM內存
ReservedOsMemory 保留的操作系統內存
ThreadStackSize 線程棧的大小
例如:運行的環境 (有必要說明一下,不同環境會有不同的結果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse 3.4
結合上面例子我們來對公式說明一下:
MaxProcessMemory 在32位的 windows下是 2G
JVMMemory eclipse默認啟動的程序內存是64M
ReservedOsMemory 一般是130M左右
ThreadStackSize 32位 JDK 1.6默認的stacksize 325K左右
公式如下:
(2*1024*1024-64*1024-130*1024)/325 = 5841
公式計算所得5841,和實踐5602基本一致(有偏差是因為ReservedOsMemory不能很精確)
由公式得出結論:你給JVM內存越多,那么你能創建的線程越少,越容易發生java.lang.OutOfMemoryError: unable to create new native thread。
加上下面的JVM參數,測試結果如下:
ThreadStackSize JVMMemory 能創建的線程數
默認的325K -Xms1024m -Xmx1024m i = 2655
默認的325K -Xms1224m -Xmx1224m i = 2072
默認的325K -Xms1324m -Xmx1324m i = 1753
默認的325K -Xms1424m -Xmx1424m i = 1435
-Xss1024k -Xms1424m -Xmx1424m i = 452
——————————————————————————————————————————
內存泄漏導致的堆棧溢出:
java.lang.OutOfMemoryError: unable to create new native thread 【問題定位】: 對於一般的內存泄漏導致的堆棧溢出,通常的錯誤信息主要有以下幾種。 1. java.lang.OutOfMemoryError: Java heap space 2. java.lang.OutOfMemoryError: PermGen space 3. java.lang.OutOfMemoryError: Requested array size exceeds VM limit 4. java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)
前兩種是程序級別的問題,導致的堆棧溢出。這兩種情況必須對代碼問題處理解決
解決此類問題:
1、 如果程序中有bug,導致創建大量不需要的線程或者線程沒有及時回收,那么必須解決這個bug,修改參數是不能解決問題的。
2、 如果程序確實需要大量的線程,現有的設置不能達到要求,那么可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個因素,來增加能創建的線程數:
a. MaxProcessMemory 使用64位操作系統
b. JVMMemory 減少JVMMemory的分配
c. ThreadStackSize 減小單個線程的棧大小