当 OutOfMemory 是由于 "unable to create new native thread" 时的堆转储

Heap dump when OutOfMemory is due to "unable to create new native thread"

我们最近在 Tomcat 服务器上由于 "unable to create new native thread" 而出现内存不足。我们知道问题出在哪里 - 有一个错误产生了太多的线程,超出了框上 ulimit 允许的范围。

令我感兴趣的是,发生这种情况时 JVM 没有转储堆。我检查了 Java 6 和 8 中的行为是否一致。

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

转储堆 - TraditionalOOM.groovy:

byte[] b = new byte[1000000000]

是否转储堆 - ManyThreads.groovy:

int MAX = 5000;

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

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

Thread.activeCount();

与此问题相关的 Java 选项(恕我直言)有以下 2 个:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/somewhere

我想知道:


更新

我得到了答案 - 似乎这是预期的行为,Oracle(或 Sun)已将此行为作为缺陷拒绝 - http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=74ee28dae329645479a51f6c78f2?bug_id=6784422

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

http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=74ee28dae329645479a51f6c78f2?bug_id=6784422

link 表示 "Allocation of a native thread is not from the heap or the permanent generation - hence failure to allocate one does not result in a heap dump. (There would be little point in dumping the heap as that is not what was exhausted.)"

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