Java 当OutOfMemory由于“";无法创建新的本机线程";

Java 当OutOfMemory由于“";无法创建新的本机线程";,java,multithreading,jvm,out-of-memory,heap-dump,Java,Multithreading,Jvm,Out Of Memory,Heap Dump,由于Tomcat服务器上“无法创建新的本机线程”,我们最近出现了OutOfMemory。我们知道问题是什么——有一个bug产生了太多线程,超出了机箱上允许的线程数 让我感兴趣的是,当这种情况发生时,JVM没有转储堆。我检查了它在Java6和Java8中的行为是否一致 我编写了一些快速Groovy POC来证明这种行为。因此,虽然我在这里使用了groovy,但其行为与我的Servlet应用程序是一致的(对我来说,共享问题的工作模型更容易) 转储堆-TraditionalOOM.groovy: by

由于Tomcat服务器上“无法创建新的本机线程”,我们最近出现了OutOfMemory。我们知道问题是什么——有一个bug产生了太多线程,超出了机箱上允许的线程数

让我感兴趣的是,当这种情况发生时,JVM没有转储堆。我检查了它在Java6和Java8中的行为是否一致

我编写了一些快速Groovy POC来证明这种行为。因此,虽然我在这里使用了groovy,但其行为与我的Servlet应用程序是一致的(对我来说,共享问题的工作模型更容易)

转储堆-
TraditionalOOM.groovy

byte[] b = new byte[1000000000]
int MAX = 5000;

for (int i = 0; i < MAX; i++) {

    new Thread() {
        public void run() {
            sleep(1000);
        }
    }.start();
}

Thread.activeCount();
不转储堆-
ManyThreads.groovy

byte[] b = new byte[1000000000]
int MAX = 5000;

for (int i = 0; i < MAX; i++) {

    new Thread() {
        public void run() {
            sleep(1000);
        }
    }.start();
}

Thread.activeCount();
我想知道:

  • 为什么JVM在OOM期间不转储堆(即使转储线程转储也会有帮助)
  • 答案是否显而易见,JVM没有执行转储的线程

更新


我得到了我的答案-似乎这是预期的行为,Oracle(或Sun)将此行为作为缺陷拒绝了-

我得到了我的答案-似乎这是预期的行为,Oracle(或Sun)将此行为作为缺陷拒绝了-

该链接声明“本机线程的分配不是来自堆或永久生成,因此分配失败不会导致堆转储(转储堆没有什么意义,因为这不是已耗尽的内容)。”


我并不完全同意这一点,因为堆转储也有大量关于线程的信息。如果这是Oracle(或Sun)的立场,JVM至少应该转储线程转储。

我得到了答案-似乎这是预期的行为,Oracle(或Sun)已将此行为作为缺陷拒绝了-

该链接声明“本机线程的分配不是来自堆或永久生成,因此分配失败不会导致堆转储(转储堆没有什么意义,因为这不是已耗尽的内容)。”


我并不完全同意这一点,因为堆转储也有大量关于线程的信息。如果线程转储是Oracle(或Sun)的位置,JVM至少应该转储线程转储。

我从未使用Oracle/Sun JVM进行过此操作,但我知道可以将IBM JVM配置为在相当任意的条件下丢弃javacore或堆转储,如感兴趣的特定异常,介意与IBM VM共享您使用的选项吗?我可能可以在Oracle VM的线上寻找一些东西。谢谢。我从来没有在Oracle/Sun JVM上这样做过,但我知道可以将IBM JVM配置为在相当任意的条件下丢弃javacore或堆转储,例如特定异常。这很有趣,介意与IBM VM共享您使用的选项吗?我可能可以在Oracle VM的线上寻找一些东西。谢谢