繁体   English   中英

Java GC 上的低内存停止和崩溃程序

[英]Java GC on low memory stop and crash program

我在我的 java 程序中使用并行 GC。 但是当 jvm 的空闲内存少于 ~400mb 时,GC 开始消耗所有 CPU。 一段时间后,jvm 崩溃,出现java.lang.OutOfMemoryError: GC overhead limit exceeded 但是我正在使用Runtime.getRuntime().freeMemory()打印可用内存量,并且我确信 jvm 有 ~400mb 的可用空间。 我试图将-XX:MinHeapFreeRatio设置为 1 或 5,但这让一切变得更糟。

如何配置 GC 或者我应该选择哪一个来防止它消耗所有 CPU 并导致 jvm 崩溃? 我的 jvm 标志是-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Xmx3800m -server -Djava.library.path="native_libs"

错误

当 JVM 花费大部分时间进行垃圾收集而在垃圾收集周期结束时无法释放大量内存时,会出现错误java.lang.OutOfMemoryError: GC overhead limit exceeded 一个很好的详细描述可以在 这里找到。 请注意,这并不一定意味着您的内存不足! 您可能还有很多内存,但垃圾收集器可能无法释放任何内容并提前放弃。

原因

由于您说在发生此异常时只需要 50 mb 内存,因此您可能会泄漏内存。 仅使用 50 mb 内存不会导致垃圾收集器像这样失败。 当您仍然引用不再需要的对象时,就会发生内存泄漏。 当太多对象仍然可以访问时,垃圾需要很长时间,垃圾收集器无法释放任何对象,因为它们仍然可供程序访问。

解决方案

您需要找到内存泄漏的来源。 常见的原因是将对象保留在列表、映射和集合等数据结构中而不删除它们。 您可以进行堆转储,这实际上将 Java 程序内存中的所有对象保存到一个文件中,然后您可以检查该文件。 通过将-XX:+HeapDumpOnOutOfMemoryError标志添加到您的java命令,您可以将 java 配置为在发生 OutOfMemoryException 时执行堆转储。 有关堆转储存储位置的更多详细信息可以在此问题Using HeapDumpOnOutOfMemoryError parameter for heap dump for JBoss 上找到 然后,下次发生故障时,您可以使用Eclipse MAT 之类的工具来检查堆转储并查看哪些对象正在消耗内存。 这将为您指明内存泄漏的方向,以便您可以修复它。

我的应用程序在老一代中有很多东西,所以我如何理解 GC 试图为年轻一代释放足够的内存并且经常进行完整的 gc。 因此,通过减少 Young gen 的大小,我扩展了 old gen 的大小,这是我大量使用的。

要减少 Young gen 大小,您可以使用-XX:MaxNewSize-XX:NewRatio-XX:NewSize 我使用了-XX:MaxNewSize 你可以在这里阅读它https://docs.oracle.com/cd/E19900-01/819-4742/abeik/index.html

java.lang.OutOfMemoryError异常是内存泄漏的一种常见迹象。

通常,当Java 堆中没有足够的空间分配对象时会抛出此错误。 在这种情况下,垃圾收集器无法腾出空间来容纳新对象,堆也无法进一步扩展。

此外,当本机内存不足以支持 Java 类的加载时,可能会抛出此错误。

在极少数情况下,当花费过多时间进行垃圾收集并且释放的内存很少时,可能会抛出java.lang.OutOfMemoryError

详情在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM