1.常见的源码OutOfMemoryError 问题之GC overhead limit exceeded 问题详解
常见的OutOfMemoryError 问题之GC overhead limit exceeded 问题详解
性能问题,上 HeapDump性能社区!源码 本文来自社区OOM原理详解系列,源码更多OOM相关源码和案例去 HeapDump性能社区。源码
Java 运行时环境包含一个内置的源码垃圾回收 (GC)进程。在许多其他编程语言中,源码牛熊bbl指标源码和指标源码开发人员需要手动分配和释放内存区域,源码以便可以重用释放的源码内存。
另一方面,源码Java 应用程序只需要分配内存。源码每当内存中的源码特定空间不再使用时,称为垃圾收集的源码单独进程会为它们清除内存。垃圾收集手册中更详细地解释了 GC 如何检测内存的源码特定部分,但您可以相信 GC 能很好地完成它的源码工作。
在GC开销超过极限:java.lang.OutOfMemoryError时显示错误,源码您的应用程序已经耗尽了几乎所有的可用内存,GC一再未能清除它。
该java.lang.OutOfMemoryError:GC开销超过极限错误信号,表示您的应用程序花费太多的时间进行垃圾收集而回收不到太多结果。
如果这个GC开销限制不存在,会发生什么?请注意,xutils 源码java.lang.OutOfMemoryError: GC 开销限制超出错误仅在几次GC循环后释放 2% 的内存时才会抛出。这意味着GC能够清理的少量堆可能会再次被快速填满,从而迫使GC再次重新启动清理过程。这形成了一个恶性循环,CPU % 忙于GC,无法完成任何实际工作。应用程序的最终用户面临极端的减速——通常在几毫秒内完成的操作需要几分钟才能完成。
因此,“java.lang.OutOfMemoryError: GC 开销限制超出”消息是快速失败原则的一个很好的例子。
在以下示例中,emui 源码我们通过初始化 Map 并在未终止的循环中将键值对添加到映射中来创建“超出 GC 开销限制”错误:
正如您可能猜到的那样,这不会有好的结局。事实上,当我们启动上述程序时:
我们很快就会遇到java.lang.OutOfMemoryError: GC 开销限制超出消息。但是上面的例子很棘手。当使用不同的 Java 堆大小或不同的 GC 算法启动时,我的 Mac OS X .9.2 和 Hotspot 1.7.0_ 将选择不同的死亡。例如,当我以较小的 Java 堆大小运行程序时,如下所示:
应用程序将因更常见的攀源码java.lang.OutOfMemoryError: Java heap space消息而死亡,该消息在 Map resize 时抛出。当我使用除 ParallelGC之外的其他垃圾收集算法运行它时,例如 -XX:+UseConcMarkSweepGC或 -XX:+UseG1GC,错误被默认异常处理程序捕获并且没有堆栈跟踪,因为堆已经耗尽到甚至无法在异常创建时填充堆栈跟踪。
这些变化确实是很好的例子,表明在资源受限的情况下,您无法预测应用程序的死亡方式,因此不要将您的期望建立在要完成的特定操作序列上。
解决办法是写真 源码什么?作为一个诙谐的解决方案,如果您只是想摆脱“java.lang.OutOfMemoryError:GC开销限制超出”消息,将以下内容添加到您的启动脚本中即可实现:
我强烈建议不要使用这个选项——而不是解决问题,您只是推迟不可避免的问题:应用程序内存不足,需要修复。指定此选项只会用更熟悉的消息java.lang.OutOfMemoryError: Java heap space掩盖原始java.lang.OutOfMemoryError: GC 开销限制超出错误。
更严重的一点是——有时会触发GC开销限制错误,因为您分配给JVM的堆数量不足以满足在该JVM上运行的应用程序的需求。在这种情况下,你应该只分配更多的堆——请参阅本章末尾以了解如何实现这一点。
然而,在许多情况下,提供更多的Java堆空间并不能解决问题。例如,如果您的应用程序包含内存泄漏,添加更多堆只会推迟java.lang.OutOfMemoryError: Java heap space错误。此外,增加Java堆空间量也往往会增加影响应用程序吞吐量或延迟的GC暂停时间。
如果您希望解决Java堆空间的潜在问题而不是掩盖症状,您需要弄清楚代码的哪一部分负责分配最多的内存。换句话说,您需要回答以下问题:
此时,请确保在您的日历中清除几天(或 – 请参阅项目符号列表下方的自动方式)。以下是一个粗略的流程大纲,可以帮助您回答上述问题:
或者,我们建议Plumbr,这是唯一具有自动根本原因检测功能的Java监控解决方案。在其他性能问题中,它捕获所有java.lang.OutOfMemoryError并自动为您提供有关最需要内存的数据结构的信息。它负责在幕后收集必要的数据——这包括有关堆使用情况的相关数据(只有对象布局图,没有实际数据),以及一些您甚至在堆转储中都找不到的数据。它还会为您进行必要的数据处理——在JVM遇到java.lang.OutOfMemoryError时立即进行。这是来自Plumbr的java.lang.OutOfMemoryError事件警报示例:
无需任何额外的工具或分析,您就可以看到:
有了这些信息,您就可以放大潜在的根本原因,并确保将数据结构修剪到适合您的内存池的级别。
但是,当您从内存分析或阅读Plumbr报告得出的结论是内存使用是合法的并且源代码中没有任何更改时,您需要让您的JVM有更多的Java堆空间才能正常运行。在这种情况下,更改您的JVM启动配置并在您的启动脚本中添加(或增加值,如果存在)仅一个参数:
在上面的例子中,Java进程被分配了1GB的堆。修改最适合您的JVM的值。但是,如果结果是您的JVM仍然因OutOfMemoryError而死亡,您可能仍然无法避免上述手动或Plumbr辅助分析。