java - 由于 "unable to create new native thread"导致 OutOfMemory 时的堆转储

标签 java multithreading jvm out-of-memory heap-dump

我们最近遇到了内存不足的情况,原因是我们的 Tomcat 服务器上“无法创建新的 native 线程”。我们知道问题是什么 - 有一个错误产生了太多线程,超出了 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

我想知道:

  • 为什么 JVM 在 OOM 期间不转储堆(即使转储线程转储也会有帮助)?
  • 答案是显而易见的吗:JVM 没有线程来执行转储?
<小时/>

更新

我得到了答案 - 似乎这是预期的行为,而 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

该链接指出“ native 线程的分配不是来自堆或永久代 - 因此分配失败不会导致堆转储。(转储堆没有什么意义,因为这不是耗尽的内容。)”

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

关于java - 由于 "unable to create new native thread"导致 OutOfMemory 时的堆转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34145797/

相关文章:

python - 具有已发布的 GIL 和复杂线程的多线程代码在 Python 中速度较慢

java - 如何修复 JVM 中的单例问题?

java - 哪些编程语言只能在 JVM 上运行?

java - jhipster 和 liquibase 超时

java - 如何使用 Hibernate 将 ORM 转换为其子类?

c++ - 由于获取-释放内存顺序而错过了优化机会或所需的行为?

multithreading - Swift 有任何本地并发和多线程支持吗?

java - 处理 JVM 崩溃

java - 让 Jersey 1.x 和 2.x 共存

java - 尝试在 Jersey 2.27 中绑定(bind)工厂类时出现编译错误