首页 > 解决方案 > java OutOfMemoryException 创建新线程时,仅当活动线程数为 500 或以上时

问题描述

对于上下文,我正在运行一个修改过的 minecraft 服务器,其中一个 mods(computercraft)为您放置的每个块创建一个新线程。服务器在运行时只使用大约 15gb 的内存,但它有超过 30gb 的可用内存(-Xms8192M -Xmx32000M),所以 OOME 真的没有意义。我确实在某个地方读到过,如果活动线程过多并且您尝试创建另一个线程,则会引发 OOME,这就是让我认为存在限制的原因

每当活动线程计数(使用 VisualVM 可见)达到 500 或更多时,它会OutOfMemoryException在尝试启动新线程时抛出一个。我在互联网上找不到太多(我找到了一篇文章,但提到了 503 个线程,但他们提到的似乎没有任何帮助,而且我的服务器甚至无法超过 500)

我虽然这可能是 Docker 的问题(我使用翼手龙)所以我将 docker 的“TasksMax”变量设置为 Infinity,但这似乎没有帮助。我尝试降低堆栈大小(-Xss320k在 Xms 位之前),但这没有帮助

我还检查了系统内存使用情况,以防有任何内存泄漏,但没有。它只使用大约 50% 的内存。当我ulimit -a在linux中运行命令时,它显示的是:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 256816
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
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) 256816
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

创建新线程的示例是当新玩家加入时(因为每个玩家都有自己的 NetConnection)。这是崩溃堆栈跟踪的样子:

java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:717)
    at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378)
    at org.bukkit.craftbukkit.v1_6_R3.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:360)
    at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:831)
    at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:332)
    at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:782)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:665)
    at net.minecraft.server.ThreadMinecraftServer.run(SourceFile:583)

有谁知道是什么导致这个线程限制为 500?我修复它的唯一方法是强制杀死(thread.interrupt()然后thread.stop())最新创建的计算机线程(它们对服务器的运行能力并不那么重要,但它给玩家带来了不便,不得不重新启动计算机。我不确定是什么计算机技术在这些线程中使用的监视器/锁定类型,因此杀死它们可能很危险)

我也尝试过“java.lang.OutOfMemoryError:无法创建新的本机线程”的解释,但这似乎也没有帮助

编辑:以防万一它帮助别人,我没有找到解决办法(增加线程限制)。我认为这可能是我用来运行服务器的限制(与docker有关)。我发现这是computercraft的并行API(又名多线程)的问题,所以我不得不禁用它(通过编辑pastebin api和文本编辑器保存/退出功能)

标签: javamultithreading

解决方案


推荐阅读