尝试在高内存、许多 CPU 服务器上 运行 多次调用时 JVM 崩溃

JVM crashes when attempting to run multiple invocations on a high-memory, many CPU server

我编写了一些基于 Java 的单线程基因组学软件,这些软件 运行 一次处理一个样本,而且我有数百个样本要处理。我可以访问一台有 64 个 CPU 和 1 TB RAM 的机器,并且系统上没有其他用户。每次调用请求的最大堆大小为 8 GB。我希望我应该能够同时调用我的代码的 30 个实例(假设有两个线程——我的主线程和一个 GC 线程?)。我一次只尝试发送 20 个(使用 makefile 和 -j20 参数)。然而,实际上只有 5 运行。其余失败并显示消息:

# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.

怀疑这更多地与同时调用有关,而不是实际资源限制,我在我的程序的每次调用的执行循环中实现了一个随机的几秒延迟。这让我最多同时 运行 宁宁 10 个程序,而不是 5 个,具有相同的失败消息。

问题:

  1. 为什么尝试同时调用数十个 JVM 实例会以这种方式失败,尽管在明显具有可用资源的系统上这样做?

  2. 为什么我的 hack 实施调度延迟解决了一些问题?

  3. 同时获取所有 20 个实例 运行ning 的更好方法是什么?

这不是真正的答案,而是帮助您研究的指南。

创建一个小的虚拟程序,例如

public final class Test {
    public static void main(String[] args) throws Exception {
        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
        System.out.println(runtimeName + " Start");
        Thread.sleep(10_000L); // 10 secs
        System.out.println(runtimeName + " End");
    }
}

然后多次启动,内存大小固定,同时使用-Xms-Xmx

例如 Windows:

for /L %i in (1,1,30) do @start cmd /k java -Xms8G -Xmx8G -cp C:\path\to\class Test

在我的 Windows 7 上,有 32Gb RAM 且没有交换文件,如果我 运行 8 个 4Gb 实例,其中 3 个失败:

Error occurred during initialization of VM
Could not reserve enough space for object heap

这是意料之中的,因为 OS 和其他程序都已经在使用内存。我可以在 Windows 资源监视器中看到 "Commit Charge" 达到最大值。

所以,试试这个并在您这样做的同时监控 OS 资源。如果不使用 Windows.

,当然可以根据需要调整上述命令

默认收集器是多线程的,其线程数根据 CPU 核心数缩放。如果您一次 运行 许多 java 个实例并且每个实例只有一个线程,您可能希望切换到串行收集器,这将消耗更少的线程和线程堆栈的虚拟内存。

此外,JVM 预先保留了大量虚拟内存,可能比它在其生命周期内实际需要的多。所以你应该启用交换并允许过度使用以避免资源耗尽。