java.lang.OutOfMemoryError GC开销超出java堆空间限制



java.lang.OutOfMemoryError:java堆空间的含义该消息意味着应用程序只需要比正常操作所需的Java堆空间更多的Java堆。

java.lang.OutOfMemoryError:超过GC开销限制意味着此消息意味着,由于某种原因,垃圾收集器占用了过多的时间(默认情况下占进程所有CPU时间的98%),并且在每次运行中恢复的内存非常少(默认为堆的2%)。这在内部也意味着,当应用程序只需要比正常操作所需的Java堆空间更多的空间时。

所以我的问题是,以上两种情况中的哪一种会被触发?

因此,以下是我对以下情况的理解:-

假设我已经分配了1GB的堆大小。当前使用的堆内存为970MB。线程启动(JVM不知道它将消耗多少内存)。现在GC可以采取以下步骤之一

1) JVM开始分配内存,然后在某个时间点耗尽1GB的内存并抛出java.lang.OutOfMemoryError: Java heap space

2) GC提前运行,并尝试释放一些内存,因为它知道当前正在使用的内存接近分配的1GB,Heap。但它不能在每个空间中释放超过2%的空间随后的运行。然后它会抛出java.lang.OutOfMemoryError: GC overhead limit exceeded

就我的问题而言,我的理解正确吗?

内存不足错误:Java堆空间

JVM没有办法满足分配请求,即使在完成了它所能做的最后一搏之后也是如此。

内存不足错误GC开销限制超过

这意味着JVM可能能够满足分配请求,但在最近的一段时间里,它不得不频繁地GC,以至于花费在GC上的CPU时间超过了java进程使用的总CPU时间的一小部分(可配置)。

JVM会自行终止,而不是停留在半工作、效率低下的状态中,这种状态可能只会随着时间的推移而变得更糟。

通常禁用GC开销OOM只会在几分钟后导致Java堆空间OOM。

这基本上是一种快速失效机制。

java.lang.OutOfMemoryError: Java heap space

原因:无法在Java堆中分配对象。此错误并不一定意味着内存泄漏。这个问题可以像配置问题一样简单,其中指定的堆大小(如果没有指定,则为默认大小)对于应用程序来说是不够的。

java.lang.OutOfMemoryError: GC Overhead limit exceeded

正如你所引用的,垃圾收集花费了过多的时间。这可能是应用程序内存泄漏的副作用。旧的gen可能由于泄漏而完全满了,因此GC在垃圾收集周期中不会释放任何(或很少)垃圾。

看看这篇oracle文章,来解决不同类型的内存泄漏问题。

关于你的两个问题,我也认为你的理解是正确的,只是有点不同。第二种情况下触发GC的事件不仅仅是创建新对象。完整GC将在特定条件下触发。看看这个SE问题。

最新更新