-XX:G1保留百分比和空间耗尽

2022-09-03 07:57:03

我试图理解它到底是做什么的。我在官方文档中找到的描述并不全面:-XX:G1ReservePercent

设置保留内存的百分比以保持可用,以降低到空间溢出的风险。默认值为 10%。增加或减少百分比时,请确保将总 Java 堆调整相同的量。

对空间耗尽日志条目的描述是这样的:

当您在日志中看到到空间溢出/耗尽的消息时,G1 GC 没有足够的内存用于幸存者或提升的对象,或两者。

[...]

要缓解此问题,请尝试以下调整:

增加选项的值(以及相应的总堆)以增加“到空间”的保留内存量。-XX:G1ReservePercent

[...]

从这句话来看,这意味着在执行混合疏散时,我们没有足够的自由区域将幸存者转移到那里。to-space exhausted

但是,这与以下官方在Full GC情况下的调整建议相矛盾(强调我的):

强制 G1 更早开始标记。G1 根据较早的应用程序行为自动确定起始堆占用百分比 (IHOP) 阈值。如果应用程序行为发生更改,则这些预测可能是错误的。有两种选择:通过修改-XX:G1ReservePercent来增加自适应IHOP计算中使用的缓冲区,从而降低何时开始空间回收的目标占用率;

那么缓冲区是什么,设置做什么(从第一眼看,AdaptiveIHOP与它无关...)?-XX:G1ReservePercent

它是否始终保留一些堆空间,因此当混合疏散发生时,我们总是有空闲的区域将幸存者移动到?

或者该空间用于G1内部管理任务?如果是这样,不清楚太空包含哪些数据,所以它耗尽了?


答案 1

对我来说,了解它真正的作用,意味着去源代码。我选择了.jdk-15

此标志的最佳描述如下

它确定我们在堆中应具有的最小保留量,以最大程度地降低升级失败的可能性。

非常好,所以这与“促销失败”有关(无论这些失败是什么)。但根据你引用的粗体,这也与吗?好吧,是的,此参数仅在AdaptiveIHOP(默认情况下处于打开状态)中才重要。AdaptiveIHOP

另一件需要注意的事情是,不能保证一直保持,这是最好的努力。G1ReservePercentage

如果你看看它在下一行是如何使用的:

if (_free_regions_at_end_of_collection > _reserve_regions) {
    absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
}

事情开始变得有些意义(对于这个大胆的声明)。请注意如何提取以进行某些计算。 将为“促销失败”保留该空间(我们将对此进行介绍)。_reserve_regionsG1

如果保留该空间,则意味着可用于实际分配的空间更少。因此,如果你“增加这个缓冲区”(你按照引用的建议变得更大),你的新物体的空间会变得更,因此需要启动的时间会更快,所以需要进行空间回收的时间也会来得更早(“降低目标占用率,什么时候开始空间回收......”)。这是一个复杂的句子,但用简单的话来说,它的意思是:G1G1ReservePercentGC

如果增加 ,将需要更快地回收空间(更常见的是GC调用)。G1ReservePercentage

公平地说,这是显而易见的。并不是说我同意你应该增加这个价值,但这就是这句话所说的。


在某个 GC 周期之后,或者 知道有多少个区域是空闲的minormixedmajorG1

_free_regions_at_end_of_collection = _g1h->num_free_regions();

当然,这是“免费列表”的长度:

return _free_list.length();

基于此值和 () 加上目标暂停时间(默认情况下),它可以计算下一个周期需要多少个区域。到下一个周期结束时,可能会出现没有空区域的情况(或者空区域不能获取所有应该移动的活动对象)。应该将活动对象移动到何处(),或者,如果是碎片化 - 应该将活动对象移动到何处以进行碎片整理?这就是此缓冲区的用途。_reserve_regionsG1ReservePercent200 msEdenSurvivorold region

它充当安全网(代码中的注释使这更容易理解)。这是必要的,希望它能避免.因为如果没有自由区域(或足够多)来移动活动对象,则需要发生完整的GC(很可能后面还有一个)。Full GCyoung GC


此消息存在于日志中时,通常知道此值很小。要么增加它,要么更好地为应用程序提供更多的堆。


答案 2

推荐