100%完整的伊甸园空间,0%使用幸存者空间 – 未完成垃圾收集

我遇到了一个相当混乱的GC情况:当Eden空间100%满时,使用0%的幸存空间。 当伊甸园已满时,应该触发垃圾收集,对吧?

是否存在阻止GC守护程序运行的情况? 像一个100%的CPU?

我们正在使用jdk-1.7

可能是什么原因? 下面是jmap输出。

我们还尝试使用jmap -histo -F捕获更详细的内存使用情况,但随后CPU使用率降至0%且java进程无法访问。

 using thread-local object allocation. Parallel GC with 18 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 12884901888 (12288.0MB) NewSize = 1310720 (1.25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 85983232 (82.0MB) G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 4265738240 (4068.125MB) used = 4265738240 (4068.125MB) free = 0 (0.0MB) 100.0% used From Space: capacity = 14352384 (13.6875MB) used = 0 (0.0MB) free = 14352384 (13.6875MB) 0.0% used To Space: capacity = 14680064 (14.0MB) used = 0 (0.0MB) free = 14680064 (14.0MB) 0.0% used PS Old Generation capacity = 8589934592 (8192.0MB) used = 8589931920 (8191.997451782227MB) free = 2672 (0.0025482177734375MB) 99.99996889382601% used PS Perm Generation capacity = 41353216 (39.4375MB) used = 41079056 (39.17604064941406MB) free = 274160 (0.2614593505859375MB) 99.33702858805468% used 

当我看到你的堆配置时,我发现了

MaxNewSize = 17592186044415 MB不正确,但必须以字节为单位。

我所看到的几乎所有世代都是完整的同一时间,而Collector正试图收集这两代人,因此他们互相阻挡。

我建议请用以下参数调整内存。

 -XX:NewRatio=3 - the young generation will occupy 1/4 the overall heap -XX:NewSize - Calculated automatically if you specify -XX:NewRatio -XX:MaxNewSize - The largest size the young generation can grow to (unlimited if this value is not specified at command line) 

我还建议使用一些幸存者空间,当物体从eden复制到“终身”时,它会给时间收集器。

 -XX:SurvivorRatio=6 - each survivor space will be 1/8 the young generation 

如果幸存者空间太小,则复制集合会直接溢出到终身代。

如有任何澄清,请参阅此链接。

编辑:

-XX:NewRatio=3 – 年轻一代将占据整体堆的1/4

计算:

  y/t=1/3 y+t=h y+3y=h y=h/4 t=tenured y=young h=heap 

线程本地缓冲区是从伊甸园空间分配的。 一旦分配了缓冲区,伊甸园空间中的空闲空间就会完全减少。 这可能意味着你有许多几乎是空的TLAB,但伊甸园空间似乎已满。 当伊甸园空间中没有足够的可用空间时,将触发GC。

如果关闭-XX:-UseTLAB这将降低性能,但您可以更准确地计算空间的使用方式。

只是一个想法,但我看到老Gen也充满了。 可能是GC而不是试图清理Eden正在忙着运行完整的GC试图清理旧代以避免OOM。

幸存者比率计算:

如果SurvivorRatio = 6,那么(One SurvivorSpace:Eden)的比率=(1:6)。
所以两个幸存者将采取(2部分),伊甸园有6个部分。 总共8个部分。
因此,如果我有年轻的40 MB,Eden是(6/8 * 40)MB,一个幸存者将有(1/8 * 40)MB。

如果SurvivorRatio = 7。 然后总数是(7 + 1 + 1 = 9)。 伊甸园是(7/9 * 40)MB,幸存者将有(1/9 * 40)MB

理论上

  The SurvivorRatio parameter controls the size of the two survivor spaces. For example, -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6, each survivor space will be one eighth of the young generation. 

Mathamatically

S – 幸存者
E – Eden
Y – 年轻一代

 if SurvivorRatio=6 then S / E = 1/6 E = 6S 2S + E = Y 2S + 6S = Y S = Y / 8 

影响

如果增加到更多的SurvivorRatio值会导致Survivor的空间变小,将伊甸园空间物体直接推入旧/终身。 通过次要GC过滤Survivor Space中的镜头活动对象的机会较少。 这也可能会增加完整GC的数量。

如果将此值降低到更低的值将导致较小的伊甸园空间将使次要GC频繁发生。

要知道,如果我们使用的是串行GC算法,其中只有单个线程将用于GC,虽然您的机器是多核心机器,但更小的GC所需的时间将更加明确。

另请注意, -XX:+UseAdaptiveSizePolicy将在运行时确定JVM自身的SurvivorRatio,但最好通过尝试多次加载运行来根据您的应用程序手动提及它。