了解OutOfMemoryError

每当您发现自己盯着一个带有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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值