我在一台有15G内存的Linux机器上无法创建超过32k个Java线程。
我在一台有15G内存的Linux机器上无法创建超过32k个Java线程。
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
错误,请检查以下内容:
在小内存机器上
每个Java线程都会占用自己的堆栈内存。默认堆栈大小为1024k(= 1M)。你可以减少堆栈大小,例如java -Xss512k ...
。如果堆栈大小太低,JVM将无法启动。
同时要注意堆内存配置:(初始)-Xms
和(最大)-Xmx
。分配给堆的内存越多,可用于堆栈的内存就越少。
系统限制
ulimit -a
中的某些值可以影响线程限制。
max memory size
- 在大多数64位机器上不受限制max user processes
- linux将线程视为进程virtual memory
- 在大多数64位机器上不受限制。虚拟内存使用由-Xss配置增加(默认为1024k)你可以通过(临时)运行ulimit
命令或(永久)编辑/etc/security/limits.conf
来更改这些值。
sys.kernel.threads-max
该值是系统全局的(包括非JVM进程)最大线程数。检查cat /proc/sys/kernel/threads-max
,如果必要,增加该值。
echo 999999 > /proc/sys/kernel/threads-max
或者
sys.kernel.threads-max = 999999
在/etc/sysctl.conf
中进行永久更改。
sys.kernel.pid_max
如果cat /proc/sys/kernel/pid_max
与当前限制相似,则需要增加此值。Linux将线程视为进程。
要永久更改,可以执行以下操作之一:echo 999999 > /proc/sys/kernel/pid_max
或在/etc/sysctl.conf
中添加sys.kernel.pid_max = 999999
。
您还可能需要增加sys.vm.max_map_count
的值。可以通过执行cat /proc/sys/vm/max_map_count
来检查其值,它应该至少为(2×线程数)。
Attempt to protect stack guard pages failed.
和OpenJDK 64-Bit Server VM warning: Attempt to deallocate stack guard pages failed.
错误信息由JavaThread::create_stack_guard_pages()发出,并调用os::guard_memory()。在Linux中,这个函数是mprotect()。
要永久更改sys.vm.max_map_count
的值,可以执行以下操作之一:echo 1999999 > /proc/sys/vm/max_map_count
或在/etc/sysctl.conf
中添加sys.vm.max_map_count = 1999999
。
-Xss
栈大小选项,有没有办法查看线程使用了多少堆栈空间?知道如何配置此值很好,但我想知道是否有 JMX 指标或其他东西可以告诉我我的平均和/或最大线程堆栈利用率,以便我可以决定是否实际上需要更改此值。 - Dasmowenator针对现代 (systemd) linux 系统的额外信息。
有很多关于需要调整的值的资源(其他答案是大多数资源的良好来源);但是,通过 systemd "TasksMax" 限制实施了新的限制,它设置 cgroup 上的 pids.max。
对于登录会话,默认值为内核限制 pids_max 的 33%(通常为12,288)的UserTasksMax 可以在 /etc/systemd/logind.conf 中进行覆盖。
对于服务,默认值为内核限制 pids_max 的15%(通常为4,915)的DefaultTasksMax。您可以通过在“systemctl edit”中设置 TasksMax 或更新 /etc/systemd/system.conf 中的 DefaultTasksMax 来覆盖服务。
我在一个 Python 程序中遇到了类似的问题,以下方法对我有效。这是基于上面 maczniak 的回答和 https://superuser.com/questions/1219960/cannot-edit-proc-sys-kernel-threads-max 的内容。
echo kernel.threads-max = 1073741823 >> /etc/sysctl.conf && echo 1073741823 > /proc/sys/kernel/threads-max
echo kernel.pid_max = 999999 >> /etc/sysctl.conf && echo 999999 > /proc/sys/kernel/pid_max
echo vm.max_map_count = 2147483646 >> /etc/sysctl.conf && echo 2147483646 > /proc/sys/vm/max_map_count
echo vm.overcommit_memory = 1 >> /etc/sysctl.conf && echo 1 > /proc/sys/vm/overcommit_memory
echo fs.inotify.max_user_instances = 256 >> /etc/sysctl.conf && echo 256 > /proc/sys/fs/inotify/max_user_instances
sysctl -p
/etc/systemd/system.conf
(或对于用户运行的服务,是/etc/systemd/user.conf
)中设置DefaultTasksMax
为DefaultTasksMax=unlimited
。/etc/systemd/logind.conf
的[Login]部分中配置为UserTasksMax。UserTasksMax
设置为UserTasksMax=999999
对我有效。