我正尝试在 Red Hat Enterprise Linux Server 版本 6.5(Santiago)上启动一个进程,但由于无法分配足够的内存而失败。
# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# An error report file with more information is saved as:
问题不在于 Java 应用程序本身 - 当我简单运行以下命令时也会出现错误:
java -版本
查看内存消耗:
免费-m
total used free shared buffers cached
Mem: 32069 31276 792 0 556 16948
-/+ buffers/cache: 13771 18297
Swap: 9325 38 9287
因此 Mem 报告称 32 Gb 内存中 31 Gb 已被使用,但应该有 18 Gb 可用内存被缓存使用。当进程请求内存时,操作系统是否不应该释放其中的一部分?
错误转储的详细信息是
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# Possible reasons:
# The system is out of physical RAM or swap space
# In 32 bit mode, the process size limit was hit
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Use 64 bit Java on a 64 bit OS
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# Out of Memory Error (gcTaskThread.cpp:46), pid=40816, tid=140071992215296
#
# JRE version: 6.0_26-b03
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 compressed oops)
--------------- T H R E A D ---------------
Current thread (0x00007f6508006800): JavaThread "Unknown thread" [_thread_in_vm, id=40817, stack(0x00007f650d46c000,0x00007f650d56d000)]
Stack: [0x00007f650d46c000,0x00007f650d56d000], sp=0x00007f650d56b7c0, free space=1021k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x85ebd5] VMError::report_and_die()+0x265
V [libjvm.so+0x3e41b8] report_vm_out_of_memory(char const*, int, unsigned long, char const*)+0x68
V [libjvm.so+0x466ada] GCTaskThread::GCTaskThread(GCTaskManager*, unsigned, unsigned)+0x13a
V [libjvm.so+0x4655de] GCTaskManager::initialize()+0x21e
V [libjvm.so+0x465373] GCTaskManager::GCTaskManager(unsigned)+0x13
V [libjvm.so+0x722cad] ParallelScavengeHeap::initialize()+0x4dd
V [libjvm.so+0x836549] Universe::initialize_heap()+0xa9
V [libjvm.so+0x8360ea] universe_init()+0x7a
V [libjvm.so+0x4ac53b] init_globals()+0x4b
V [libjvm.so+0x81cc74] Threads::create_vm(JavaVMInitArgs*, bool*)+0x214
V [libjvm.so+0x51a7b0] JNI_CreateJavaVM+0x80
答案1
查看 jvm 最小最大内存,您是否使用任何 Web 服务器?查看线程数、内存设置 - 对于 Tomcat,大多数都是 @server.xml。查看 Java Mission Controlhttp://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-1998576.html获得额外的见解。Linux 通常会保留更多内存以备请求时使用。对于 Linux 上的 Java,只有 JMC 之类的东西可以帮助您了解正在发生的事情。查看 JVM 的标准输出。
答案2
问题似乎与内存无关,而是与进程限制有关。我以该用户身份运行该进程的进程限制非常低,设置为 1024。
ulimit -u 1024
并且该用户运行的所有进程的线程数接近于:
ps -eLf | grep 'myuser' | wc -l 1022
答案3
我认为我们错过了另一个也会阻止新线程创建的限制,这就是内核.pid_max限制。
root@myhost:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.7 LTS
Release: 16.04
Codename: xenial
root@myhost:~# uname -a
Linux myhost 4.4.0-190-generic #220-Ubuntu SMP Fri Aug 28 23:02:15 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
在我的系统中,这个限制是最低限制,因此它总是第一个被达到的限制,并成为我的问题的根本原因。
我发现至少在我的系统中,这个阈值 kernel.pid_max 是 32768。当我启动任何简单的 JVM 进程时,它会报告如下错误:
java/jstack/jstat ...
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# An error report file with more information is saved as:
# /root/hs_err_pid1390.log
检查内存,足够。
root@lascorehadoop-15a32:~# free -mh
total used free shared buff/cache available
Mem: 125G 11G 41G 1.2G 72G 111G
Swap: 0B 0B 0B
检查系统线程:
~# ps -eLf|wc -l
31506
但是我通过 ulimit 检查了系统限制:
root@myhost:~# 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) 515471
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 98000
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) 515471
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
从 ulimit 输出中,我们可以看到当前线程数远小于最大用户进程限制。
事实上,达到的极限是kernel.pid_max
检查和调整非常容易: https://www.cyberciti.biz/tips/howto-linux-increase-pid-limits.html
答案4
“free -g” 将为您提供当前内存使用情况,如果内存不足,则增加物理 RAM 或增加交换空间。
如果您有足够的内存,那么下一步就是增加最大用户进程数。
更改 ulimit 配置(在末尾添加以下几行)
vi /etc/security/limits.conf
* 软 nproc 65535
* 硬 nproc 65535
* 软无文件 65535
* 硬盘无文件 65535
vi /etc/security/limits.d/90-nproc.conf * 软 nproc 65535
* 硬 nproc 65535
* 软无文件 65535
* 硬盘无文件 65535