java.lang.OutOfMemoryError: unable to create new native thread
1. 理论准备
线程本质上是进程,显著区别在于线程运行在共享内存空间,而进程运行在独立内存空间,以下是相关参数:
-
/proc/sys/kernel/pid_max 决定的进程数是运行于独立内存空间的进程
-
/proc/sys/kernel/threads-max 决定的线程数是运行于共享内存空间的线程
-
ulimit -u 指的是一个用户在同一时间最多能拥有的总进程(含线程)
-
ulimit 的进程数(含线程)受限于 pid_max 及 threads-max
2. 排查
一般由于两个原因导致的:
1)内存空间不足以满足创建线程所需的stack size virtual memory < stack size*the number of threads 2)线程数已达到操作系统的上限
最大线程数计算方法:
# 计算公式为: default_nproc = max_threads / 2; # 其中, max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE); # mempages是机器的物理页面个数, THREAD_SIZE=8K, 所以, 计算公式为: default_nproc = max_threads / 2 = (mempages * PAGE_SIZE) / ( 2 * 8 *THREAD_SIZE ) = total_memory / 128K; # 计算本机默认nproc配置: cat /proc/meminfo | grep MemTotal MemTotal: 115571480 kB echo "115571480 / 128" | bc 902902 ulimit -u 902682 # 算出来default_nproc = 902902, 和实际的902682很接近, # 因为物理页面会存储一些关键数据, 所以实际的比计算出来的要小一些.
2.1. 线程数
jvm stack size 相关参数
java -XX:+PrintFlagsFinal -version | grep ThreadStackSize
操作系统相关参数
#进程可用最大虚拟内存 ulimit -v #最大栈大小 ulimit -s #每个用户可创建最大进程数 ulimit -u #查看全部设置 ulimit -a #系统内存 free -h #java线程设置 java -XX:+PrintFlagsFinal -version | grep ThreadStackSize #系统支持的最大进程数 cat /proc/sys/kernel/pid_max #共享内存最大线程数 cat /proc/sys/kernel/threads-max #查询当前系统已用的进程数 ps -elf | wc -l #查询当前系统已用的线程和进程数 ps -eLf | wc -l #获取进程id ps -ef | grep <key word> #查询当前某程序的线程或进程数 ps -p <pid> -Lf | wc -l