Java.lang.OutOfMemoryError: 无法创建新的本地线程

163

在8GB RAM VM中,当线程数达到32k时(ps -eLF| grep -c java),我们遇到了"java.lang.OutOfMemoryError : unable to create new native Thread"错误。

然而,"top"和"free -m"显示有50%的可用内存。JDK是64位的,尝试过HotSpot和JRockit。服务器运行Linux 2.6.18。

我们还尝试了OS堆栈大小(ulimit -s)的调整和最大进程(ulimit -u)限制、limit.conf的增加,但都无济于事。

我们几乎尝试了所有可能的堆大小组合,包括保持较低或较高等。

我们用以下脚本来运行应用程序:

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties

我们尝试编辑 /etc/security/limits.conf 和 ulimit,但问题仍然存在。

[root@jboss02 ~]# 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) 72192
max locked memory       (kbytes, -l) 32
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) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

13
操作系统对于能够创建的线程数量是有限制的。为什么你要创建超过32k个线程?你的系统很可能没有成千上万个处理器核心,创建如此多的线程是没有用的。相反,应该使用线程池(ExecutorService)来管理线程。 - Jesper
谢谢回复。我们正在使用一个开源库并尝试进行负载测试。任何该开源库都会创建很多线程。但我不明白的是,当“top”显示50%的空闲内存时,为什么会出现OutOfMemory错误。 - Deepak Tewani
我们在ICE4j库中使用的开源库。 - Deepak Tewani
17
OutOfMemoryError并不一定意味着堆空间或"通用"内存已耗尽。在这种情况下,明显是由于操作系统没有足够资源来分配额外的线程导致失败。有50%的空闲内存与这种特定的故障无关。 - Andrzej Doyle
2
创建新线程需要哪些其他资源?我们的印象是,如果增加RAM,则可以创建更多的线程。请指导我们。 - Deepak Tewani
显示剩余3条评论
15个回答

1
如果您的工作因节点上的OutOfMemory而失败,您可以调整每个节点的最大映射和减少器数量以及JVM选项。根据数据节点的特定硬件,通常需要增加mapred.child.java.opts(默认值为200Xmx)。

此链接可能会有所帮助。


1
我们已经尝试了那个链接上提供的更改,但结果仍然相同 :( - Deepak Tewani

1

您的JBoss配置存在一些问题, /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms和Xmx限制了您的JBoss内存使用量,仅使用配置值,因此从您拥有的8GB中,服务器仅使用512M +一些额外的空间用于其自身目的,增加该数字,记得为操作系统和其他正在运行的程序留出一些空闲空间,也许您可以使其运行,尽管代码不太好。 如果您能修复代码,那就太好了。


0

我曾经遇到过同样的问题,结果发现是使用了不正确的Java API。我在批处理方法中初始化了一个构建器,但这个构建器不应该被初始化超过一次。

基本上,我的做法是:

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}

我本应该这样做:

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

0

你是否正在使用system.d启动你的Java应用程序?这篇文章适合你!

最近我偶然发现DefaultTasksMax [1]在我的机器上被限制为60,这对于我的新keycloak安装来说是不够的。

一旦达到“60”限制(ps -elfT | grep keycloak|wc -l),Keycloak就会崩溃并显示java.lang.OutOfMemoryError : unable to create new native Thread

解决方案

1. 查看你的system.d设置

systemctl show --property DefaultTasksMax

在我的情况下,这将打印出60

2. 提供一个更高的值

editor /etc/systemd/system.conf

编辑:

DefaultTasksMax=128

您还可以在Unit文件中设置类似的值TaskMax。请参见[2]。

3. 重新加载、检查、重启

systemctl daemon-reload
systemctl show --property DefaultTasksMax
systemctl start keycloak


[1] https://www.freedesktop.org/software/systemd/man/systemd-system.conf.html [2] https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html

-6
首先,我不会太怪罪操作系统/虚拟机,而是开发人员编写了创建如此多线程的代码。 基本上,在您的代码(或第三方)中创建了大量未受控制的线程。 仔细检查堆栈跟踪/代码并控制创建的线程数量。通常情况下,您的应用程序不应该需要大量线程,如果确实需要,则是不同的问题。

11
这不是对问题的解决方案。 - ftrujillo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接