这实际上是最初发布于2010年的帖子的转世。 昨天,当听到我们的工程师咒骂一个特别令人讨厌的错误时,闪回发生了。 当诅咒停止时,我走过去核实我的怀疑。 瞧,我是正确的–情绪波动是由应用程序用尽了堆空间导致的,但死于没有通常的OutOfMemoryError症状。
因此,让我通过三年前我第一次遇到的相同代码示例来说明缺少OutOfMemoryError的情况。 那时我使用的是Windows XP,安装了2010年中期的JDK 6。
我在玩的是Plumbr的早期发行版,该发行版应该是从应用程序中发现内存泄漏的。(编辑:那时,它除了崩溃JDK之外几乎没有做任何事情)。 为了验证这一点,我写了一个小片段,我认为这对于泄漏发现是一个很好的测试用例(编辑:实际上不是)。 我能够创建并启动以下命令:
class Leak { static List list = new ArrayList(); public static void main(String[] args) { for (int i = 0; i >= 0 ;i++) { list.add(i); } System.out.println("I will either reach here or die trying"); }
}
对于marketoid来说相当不错,是吗? 但是您认为运行显示在我的命令提示符下的代码是什么:
选项A:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:2760)at java.util.Arrays.copyOf(Arrays.java:2734)at java.util.ArrayList.ensureCapacity(ArrayList.java:167)at java.util.ArrayList.add(ArrayList.java:351)at Leak.main(Leak.java:6)
选项B:
I will either reach here or die trying
好吧,正如我发现的那样,它什么都不会打印出来,所以我几乎只能盯着空的命令提示符。
由于距离我上一次真正的Java开发经验只有两年,之后才被降级为管理人员,所以我没有时间进行故障排除。 因此,我将样本带给了铁杆Java黑客,这些黑客后来被称为Zeroturnaround的创始人。 在过去的十分钟中,我设法使它们看上去也眼花azz乱,在它出现之前-内存的分配方式使得没有空间可以创建new OutOfMemoryError()
。
如果使用2010年中的JDK版本在Windows XP上以64MB堆(默认)执行上述操作,则会看到无提示失败:
C:\work\snippets\leak java -Xmx64m Leak
C:\work\snippets\leak
但是,如果您稍微增加(实际上可以修改)堆大小,则会遇到更熟悉的情况:
C:\work\snippets\leak java -Xmx65m Leak
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:2760)at java.util.Arrays.copyOf(Arrays.java:2734)at java.util.ArrayList.ensureCapacity(ArrayList.java:167)at java.util.ArrayList.add(ArrayList.java:351)at Leak.main(Leak.java:6)
C:\work\snippets\leak
故事的道德启示? 我只能建议升级到一个更现代的版本–不管我尝试了哪种配置,我都无法使用今天在Mac上拥有的JDK 7版本来重新创建这种情况。 但是,查看有关流行的Java运行时配置的统计信息,您会发现可追溯到2010年之前版本的JDK部署数量惊人,这意味着问题仍然存在,迫使开发人员疯狂地通宵达旦,试图找出源代码。这个问题没有来自堆栈跟踪的任何提示来支持它们。
无论如何,以我对JDK 6内部的广泛知识支持工程团队,我继续前进,并从我曾经贡献过的被人们遗忘的博客中恢复了这篇帖子。
翻译自: https://www.javacodegeeks.com/2013/10/running-out-of-memory-without-the-outofmemoryerror.html