首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java --为什么GC次数会随着堆的增长而增加(就容量而言)?

Java --为什么GC次数会随着堆的增长而增加(就容量而言)?
EN

Stack Overflow用户
提问于 2020-02-29 11:16:02
回答 2查看 115关注 0票数 0

至少在旧的GCs中,这是正确的。(我知道有一些像ZGC和Shenandoah这样的新公司致力于消除这种情况)

据我所知,GC保存有生命对象的轨迹,那么GC时间不应该主要受对象数量(活动/需要清除)的影响吗?

编辑:i的意思是在容量方面增长,意味着堆更大,但应用程序对它的利用率是相同的。

EN

回答 2

Stack Overflow用户

发布于 2020-02-29 11:26:31

你没回答自己的问题吗?

据我所知,

保存有活动对象的跟踪,所以GC时间不应该主要受对象数量(活动/需要清除)的影响吗?

堆增长得越多,拥有的活动对象越多,GC就越慢(我肯定这条规则有例外,特别是对于小集合,但这是一个粗略的想法)。要清除的对象数量是不相关的,最重要的是活动对象的总数。现在,如果您的堆正在增长,因为您正在存储长期存在的对象,那么只要您不继续添加更多的对象,它可能是可以的。最终,长寿的物体将向幸存者空间移动,并且只会受到大型收藏的影响,而不会受到次要的影响。只要小GC始终能从年轻一代中获得足够的内存,就不会在所有对象(包括长寿对象)上触发主GC。

我还观察到了G1的不同行为。我们有一个低延迟的应用程序(40 5ms p99),所以我们尝试配置G1来进行非常短的暂停(不记得有多少,也许5ms左右)。发生的情况是,G1或多或少地达到了5ms的目标,但它必须非常频繁地运行,因为5ms不足以处理堆中的所有死对象。因此,不完全正确地说,随着堆大小的增加,单个垃圾收集的运行速度会变慢,但是,在给定的一段时间内,垃圾收集的平均时间很可能会增加。

票数 0
EN

Stack Overflow用户

发布于 2020-03-03 22:38:51

有许多不同的算法可以用来实现垃圾收集。并不是所有的人都表现出你提到的行为。

在你的问题中,你指的是使用标记扫描形式的算法。如果我们以HostSpot JVM为例,可以使用CMS收集器收集旧一代。这使用了标记阶段,其中所有可从应用程序代码访问的对象都被标记。最初,一组直接可访问的对象(堆栈上的对象引用、寄存器等)。被创造出来了。该集合中的每个对象都在其标头中设置了标记位,以指示其仍在使用中。来自这些对象的所有引用都是递归的,并且每个可访问的对象都有标记位集。这需要多长时间与活动对象的数量成正比,而不是堆的大小。

然后,扫描阶段必须扫描整个堆,寻找具有标记位集的对象,并确定它们之间的间隙,以便将它们添加到空闲列表中。这些被用来为年轻一代所推广的对象分配空间。因为必须对整个堆进行扫描,因此所花费的时间与堆的大小成正比,而不管堆中有多少活数据。

在G1的情况下,算法是相似的,但是每一代堆被划分成区域,这样就可以更有效地回收空间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60464538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档