Java 当OutOfMemory由于“";无法创建新的本机线程";
由于Tomcat服务器上“无法创建新的本机线程”,我们最近出现了OutOfMemory。我们知道问题是什么——有一个bug产生了太多线程,超出了机箱上允许的线程数 让我感兴趣的是,当这种情况发生时,JVM没有转储堆。我检查了它在Java6和Java8中的行为是否一致 我编写了一些快速Groovy POC来证明这种行为。因此,虽然我在这里使用了groovy,但其行为与我的Servlet应用程序是一致的(对我来说,共享问题的工作模型更容易) 转储堆-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
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的线上寻找一些东西。谢谢