Java OutOfMemoryError Unable To Create New Native Thread - Java 147

Java OutOfMemoryError Unable To Create New Native Thread – Java 147

無法建立新的執行緒,因為每個執行都需要佔用一定的記憶體空間,當 JVM 向底層 OS 請求建立一個新的執行緒時,如果沒有足夠的資源分配就會拋出此錯誤,模擬無窮迴圈建立執行緒,直到 JVM 拋出錯誤, Java 147 增加了範例,並透過單元測試來驗證產出結果。

Java OutOfMemoryError

Unable To Create New Native Thread

無法建立原生執行緒,設定 JVM Arguments。
-Xmn30m -Xms120m -Xmx120m

檔案目錄

./
   +- src
       +- test
       |   +- org
       |       +- ruoxue
       |           +- java_147
       |               +- memory
       |                   +- UnableToCreateNewNativeThreadTest.java 

Java Heap Space

有以下幾種情境:

  1. 執行緒數超過 OS 最大限制。
  2. 執行緒數超過 kernel.pid_max。
  3. OS 記憶體不足。

max user processes

查看設置。

ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3880
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3880
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

最大程序數,目前設置 3880

kernel.pid_max

查看目前程序數設定。

cat /proc/sys/kernel/pid_max
3880

測試 JUnit 4

thread

無窮迴圈建立執行緒,重複建立過程。

@Test
	public void thread() {
		for (;;) {
			new Thread(() -> {
				try {
					Thread.sleep(Integer.MAX_VALUE);
				} catch (InterruptedException e) {
				}
			}).start();
		}
	}
java.lang.OutOfMemoryError: unable to create new native thread
	at java.lang.Thread.start0(Native Method)
	at java.lang.Thread.start(Thread.java:719)
	at org.ruoxue.java_147.memory.UnableToCreateNewNativeThreadTest.thread(UnableToCreateNewNativeThreadTest.java:15)

UnableToCreateNewNativeThreadTest.java

package org.ruoxue.java_147.memory;

import org.junit.Test;

public class UnableToCreateNewNativeThreadTest {

	@Test
	public void thread() {
		for (;;) {
			new Thread(() -> {
				try {
					Thread.sleep(Integer.MAX_VALUE);
				} catch (InterruptedException e) {
				}
			}).start();
		}
	}
}

修改設定

暫時修改,重啟機器後會失效。

ulimit -u 65535

永久修改。

vim /etc/security/limits.d/20-nproc.conf
*          soft    nproc     65535
*          hard    nproc     65535

暫時修改,重啟機器後會失效。

echo 65535 > /proc/sys/kernel/pid_max

永久修改。

vim /etc/sysctl.conf
kernel.pid_max = 65535

重載生效

sysctl -p

心得分享

  1. 考慮降低程式中建立執行緒的數量,分析系統應用是否真的需要建立這麼多執行緒。
  2. 如果真的需要建立大量執行緒,調整 OS 的線程最大數量。

發佈留言