Java JVM在试图在内存高、CPU多的服务器上运行多个调用时崩溃

Java JVM在试图在内存高、CPU多的服务器上运行多个调用时崩溃,java,jvm,multiprocessing,Java,Jvm,Multiprocessing,我编写了一些基于Java的单线程基因组学软件,每次运行一个样本,我有数百个样本要处理。我可以访问一台有64个CPU和1 TB RAM的机器,并且系统上没有其他用户。每次调用请求的最大堆大小为8 GB。我希望我能够同时调用代码的30个实例(假设有两个线程——我的主线程和一个GC线程?)。我只尝试一次分派20个(使用makefile和-j20参数)。然而,在实践中,只有5次运行。其余部分失败,并显示以下消息: # There is insufficient memory for the Java R

我编写了一些基于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个程序,并显示相同的失败消息

问题:

  • 为什么在一个显然拥有可用资源的系统上同时调用几十个JVM实例却以这种方式失败

  • 为什么我的黑客实现调度延迟解决了一些问题

  • 让所有20个实例同时运行的更好方法是什么

  • 这不是一个真正的答案,而是一个帮助你研究的指南

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

    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上:

    (1,1,30)do@start cmd/k java-Xms8G-Xmx8G-cp C:\path\to\class Test中的/L%i的
    
    
    在具有32Gb RAM且无交换文件的Windows 7上,如果我运行8个4Gb实例,其中3个会出现以下故障:

    初始化VM期间发生错误 无法为对象堆保留足够的空间 这是意料之中的,因为操作系统和其他程序都已经在使用内存了。我可以在Windows资源监视器中看到“提交费用”达到最大值


    因此,请尝试此操作,并在执行此操作时监视操作系统资源。当然,如果不使用Windows,请根据需要调整上述命令。

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


    此外,JVM预先保留了大量虚拟内存,可能比其生命周期中实际需要的内存还要多。因此,您应该启用交换并允许overmit以避免资源耗尽。

    根据设置,Java可能会使用比GC使用的线程更多的线程。这就是说,除了明显的速度减慢之外,拥有比内核更多的线程应该根本不是问题。我知道这不是答案,但我可能会尝试在单个JVM中运行所有并行任务。当应用程序崩溃时,我肯定会请求至少一个线程转储,但也可能是堆转储。可能不是系统限制,而是用户/项目对内存或线程数的限制。选中“ulimit-Sa”。您还应该检查一个JVM的内存和线程使用情况(DirectMemory、PermSpace、Stacks都会消耗大量的额外资源)。使用所有CPU不需要多个JVM。什么会阻止你拥有一个JVM?谢谢大家的帮助!正如您和biziclop所建议的,我认为GC使用的线程远远不止一个。我在JVM调用中添加了
    -XX:+UseSerialGC
    参数,这似乎完全解决了这个问题。我现在有20个作业同时运行!