每当您发现自己盯着一个带有OutOfMemoryError的堆栈跟踪时,它应该都非常清晰。 该程序不再有肘部空间,并且由于缺少它而濒临死亡。 从10,000英尺或高管椅子上可能已经包含太多信息。 但是,那些必须构建或维护应用程序并弄清为什么会产生特定错误的人员–我们可以对问题进行更多的了解。
在本文中,我们将了解不同的OutOfMemoryError消息的实际含义。 我们从最常见的情况开始,然后发展到更有趣的情况。
- java.lang.OutOfMemoryError:Java堆空间
- java.lang.OutOfMemoryError:PermGen空间
- java.lang.OutOfMemoryError:超出了GC开销限制
- java.lang.OutOfMemoryError:无法创建新的本机线程
- java.lang.OutOfMemoryError:nativeGetNewTLA
- java.lang.OutOfMemoryError:请求的数组大小超出了VM限制
- java.lang.OutOfMemoryError:请求<reason>的<size>个字节。 交换空间不足?
- java.lang.OutOfMemoryError:<原因> <堆栈跟踪>(本机方法)
java.lang.OutOfMemoryError:Java堆空间 。 我们从大家看到的比实际想要的更多的视频开始。 这是Java虚拟机通知您虚拟机堆区域中没有更多空间的方式。 您正在尝试创建一个新的对象,但是这个新创建的结构将要消耗的内存量超过了JVM在堆中的拥有量。 JVM试图通过在丢弃之前调用完整的GC来释放内存,但没有成功。 消除症状的最快方法是通过-Xmx参数增加堆。 请注意,本文中的该建议或其他建议均应加盐。 很多时候,您最终只会隐藏潜在问题的症状。
下一个嫌疑犯也很常见。 我想你们大多数人在重新部署期间都看到了java.lang.OutOfMemoryError:PermGen空间 。 它与第一个消息几乎是相同的消息,但是您现在正在尝试在永久代区域中分配内存,而不是堆。 同样,您没有足够的空间,因此JVM本机代码足以让您了解它。 如果增加-XX:MaxPermSize参数,则此消息趋于消失(一段时间)。
第三个-java.lang.OutOfMemoryError:超出了GC开销限制 –是有点不同的野兽。 JVM并未发出丢失堆/ permgen的信号,而是发出信号,表明您的应用程序在垃圾回收中花费了太多时间而几乎没有显示。 默认情况下,如果您在GC中花费了总时间的98%以上,并且在GC中恢复了不到2%的堆之后,则JVM配置为抛出此错误。 听起来像是一个完美的地方,可以采用“快速故障”防护措施。 在极少数情况下需要禁用它,请在启动脚本中添加-XX:-UseGCOverheadLimit 。
前三个OutOfMemoryError消息最多执行我们使用Plumbr解决的情况的98%。 因此,您很有可能不知道其余的三重奏。
java.lang.OutOfMemoryError:如果JVM从操作系统要求一个新线程,并且基础OS无法再分配新线程,则将收到一条消息,提示您无法创建新的本机线程 。 此限制与平台密切相关,因此,如果您想知道自己的限制,请使用以下代码段运行自己的小实验。 在运行最新JDK 7的64位MacOS X上,创建线程#2032时遇到麻烦。
while(true){new Thread(new Runnable(){public void run() {try {Thread.sleep(10000000);} catch(InterruptedException e) { } } }).start();
}
java.lang.OutOfMemoryError:nativeGetNewTLA是JVM无法分配新线程本地区域的症状。 这是您仅在jRockit虚拟机上遇到的问题。 如果您还记得的话,线程局部区域是用于在多线程应用程序中有效分配内存的缓冲区。 每个线程都有其自己的预分配缓冲区,该线程实例化的所有对象都在该缓冲区中出生。 在高度多线程的应用程序中创建大量对象时,您会遇到问题,在这种情况下,您可能需要调整-XXtlaSize参数。
java.lang.OutOfMemoryError:请求的数组大小超出VM限制是一条消息,当您尝试创建大于VM限制所允许的数组时,您会发现自己一直盯着它。 在具有最新JDK 7版本的64位Mac OS X上,我发现自己承认一个事实,即带有Integer.MAX_INT-2元素的数组是可以的,但是如果仅是一根稻草,即对Integer.MAX_INT-1的使用,就会使骆驼的后背断裂。 在较旧的32位计算机上,它具有限制阵列大小以适合当时可用的微小堆的优点。 在现代的64位计算机上,似乎比实际帮助解决任何问题都造成更多的混乱。
java.lang.OutOfMemoryError:请求<reason>的<size>个字节。 交换空间不足? 当JVM无法从OS分配本机内存时,将引发此错误消息。 请注意,这与耗尽堆空间或permgen空间的标准情况完全不同。 当您在平台限制附近操作时,往往会显示此消息。 消息本身说明您可能已经超出了可用的物理和虚拟内存量。 由于后者通常是通过将内存交换到磁盘来实现的,因此您可能会想到的快速解决方案是增加交换文件的大小。 但是我还没有看到在交换时会正常运行的应用程序,因此这种快速修复很可能对您没有太大帮助。
java.lang.OutOfMemoryError:<原因> <堆栈跟踪>(本机方法)现在该向其他C开发人员求助了。 如消息所示,您面临本机代码的问题,但与最后一种情况相反,是在JNI或本机方法而不是JVM代码中检测到分配失败。
文章中的所有建议都应加盐。 很多时候,您最终只会隐藏潜在问题的症状。 如果要确保这些消息不是由内存泄漏引起的,请免费下载并试用Plumbr 。
翻译自: https://www.javacodegeeks.com/2013/08/understanding-the-outofmemoryerror.html