简体   繁体   English

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

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

I am using parallel GC in my java program.我在我的 java 程序中使用并行 GC。 But when jvm have less then ~400mb of free memory GC starts to consume all of CPU.但是当 jvm 的空闲内存少于 ~400mb 时,GC 开始消耗所有 CPU。 And after some time jvm crash with java.lang.OutOfMemoryError: GC overhead limit exceeded .一段时间后,jvm 崩溃,出现java.lang.OutOfMemoryError: GC overhead limit exceeded But i am printing the amount of free memory with Runtime.getRuntime().freeMemory() , and i am sure that jvm have ~400mb of free space.但是我正在使用Runtime.getRuntime().freeMemory()打印可用内存量,并且我确信 jvm 有 ~400mb 的可用空间。 I tried to set -XX:MinHeapFreeRatio to 1 or 5 but it made everything worst.我试图将-XX:MinHeapFreeRatio设置为 1 或 5,但这让一切变得更糟。

How to config GC or which one should i choose to prevent it from consumimg all of CPU and crashing jvm?如何配置 GC 或者我应该选择哪一个来防止它消耗所有 CPU 并导致 jvm 崩溃? My jvm flags is -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Xmx3800m -server -Djava.library.path="native_libs"我的 jvm 标志是-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Xmx3800m -server -Djava.library.path="native_libs"

The Error错误

The error java.lang.OutOfMemoryError: GC overhead limit exceeded occurs when the JVM spends most of it's time garbage collecting without being able to free much memory at the end of a garbage collection cycle.当 JVM 花费大部分时间进行垃圾收集而在垃圾收集周期结束时无法释放大量内存时,会出现错误java.lang.OutOfMemoryError: GC overhead limit exceeded A good detailed description can be found here .一个很好的详细描述可以在 这里找到。 Note this does not necessarily mean that you are out of memory!请注意,这并不一定意味着您的内存不足! You may have a lot of memory left, but the garbage collector may just not be able to free anything and is giving up early.您可能还有很多内存,但垃圾收集器可能无法释放任何内容并提前放弃。

The Cause原因

Since you are saying that you only need 50 mb memory at the time this exception happens, you are likely leaking memory.由于您说在发生此异常时只需要 50 mb 内存,因此您可能会泄漏内存。 Using only 50 mb of memory would not cause the garbage collector to fail like this.仅使用 50 mb 内存不会导致垃圾收集器像这样失败。 Leaking memory happens when you still have references to objects that you no longer need.当您仍然引用不再需要的对象时,就会发生内存泄漏。 When too many objects are still accessible garbage takes a long time, and the garbage collector is not able free any Objects because they are still accessible to the program.当太多对象仍然可以访问时,垃圾需要很长时间,垃圾收集器无法释放任何对象,因为它们仍然可供程序访问。

The Solution解决方案

You need to find the source of the memory leak.您需要找到内存泄漏的来源。 Common causes are keeping objects in data structures like Lists, Maps, and Sets without removing them.常见的原因是将对象保留在列表、映射和集合等数据结构中而不删除它们。 You can take a heap dump, which essentially saves all the Objects in your java program's memory to a file, which you can then inspect.您可以进行堆转储,这实际上将 Java 程序内存中的所有对象保存到一个文件中,然后您可以检查该文件。 You can configure java to do a heap dump when an OutOfMemoryException happens by adding the -XX:+HeapDumpOnOutOfMemoryError flag to your java command.通过将-XX:+HeapDumpOnOutOfMemoryError标志添加到您的java命令,您可以将 java 配置为在发生 OutOfMemoryException 时执行堆转储。 More details about where the heap dump is stored can be found on this question Using HeapDumpOnOutOfMemoryError parameter for heap dump for JBoss .有关堆转储存储位置的更多详细信息可以在此问题Using HeapDumpOnOutOfMemoryError parameter for heap dump for JBoss 上找到 Then the next time things crash you can use a tool like Eclipse MAT to inspect the heap dump and see what objects are consuming memory.然后,下次发生故障时,您可以使用Eclipse MAT 之类的工具来检查堆转储并查看哪些对象正在消耗内存。 This will point you in the direction of your memory leak so that you can fix it.这将为您指明内存泄漏的方向,以便您可以修复它。

My app have a lot stuff in old gen, so how i understood GC was trying to free enough memory for young gen and have been making full gc very often.我的应用程序在老一代中有很多东西,所以我如何理解 GC 试图为年轻一代释放足够的内存并且经常进行完整的 gc。 So by reducing Young gen size i extend size of old gen, which was heavily used by me.因此,通过减少 Young gen 的大小,我扩展了 old gen 的大小,这是我大量使用的。

To reduce Young gen size you can use -XX:MaxNewSize , -XX:NewRatio , -XX:NewSize .要减少 Young gen 大小,您可以使用-XX:MaxNewSize-XX:NewRatio-XX:NewSize I used -XX:MaxNewSize .我使用了-XX:MaxNewSize You can read about it here https://docs.oracle.com/cd/E19900-01/819-4742/abeik/index.html你可以在这里阅读它https://docs.oracle.com/cd/E19900-01/819-4742/abeik/index.html

java.lang.OutOfMemoryError exception is one common indication of a memory leak. java.lang.OutOfMemoryError异常是内存泄漏的一种常见迹象。

Usually, this error is thrown when there is insufficient space to allocate an object in the Java heap .通常,当Java 堆中没有足够的空间分配对象时会抛出此错误。 In this case, The garbage collector cannot make space available to accommodate a new object, and the heap cannot be expanded further.在这种情况下,垃圾收集器无法腾出空间来容纳新对象,堆也无法进一步扩展。

Also, this error may be thrown when there is insufficient native memory to support the loading of a Java class .此外,当本机内存不足以支持 Java 类的加载时,可能会抛出此错误。

In a rare instance, a java.lang.OutOfMemoryError may be thrown when an excessive amount of time is being spent doing garbage collection and little memory is being freed .在极少数情况下,当花费过多时间进行垃圾收集并且释放的内存很少时,可能会抛出java.lang.OutOfMemoryError

Details here详情在这里

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

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