Java GCs开销:如果你有10mb或10g *引用的*对象,这有关系吗?

GC必须检查并找出可以收集的对象。 我的问题是,是否有太多要检查的对象会导致GC开销,或者某种程度上GC是否足够智能以避免必须遍历所有对象以找出哪个对象不再被引用?

是的,它对标记和扫描收集器确实有多少对象。 至于那些物体的大小 ,这也很重要:压缩收集器如果需要压缩10GB的东西而不是10MB的东西,还有更多的工作要做。

话虽如此,现代垃圾收集器非常复杂(它们在多个堆上运行,在后台执行操作,可以使用多个内核等)。 它们也是高度可配置的。 此外,典型的JVM配备了多个垃圾收集器。

因此很难对这样的一般问题给出有意义的,精确的答案。

优化此类事物的一种方式是分代垃圾收集的概念。 (见第4节)。 显然,自1.2以来Java已经有了世代collections。

这意味着通常较新的物体可能会更快死亡,称为“婴儿死亡率”。 这些较新的对象被置于更积极地收集的一代中。 如果一个物体已经存在了一个小时,它可能会在另外5分钟左右被放置在一个收集频率低于新物体的一代中。 如果一个物体在更频繁收集的区域中存活了一段时间,它将被提升为不太频繁收集的一代。

这使您无法查看每次扫描的所有活动对象。

这取决于正在使用哪种GC算法,在标记扫描的情况下,它确实很重要,因为标记扫描需要使用枚举来识别GC的根。 这是关于标记扫描如何工作的链接

它必须迭代所有活动对象以确定是否仍然使用对象。 G1收集器有1 MB的巨型对象(它知道1 MB内的所有引用),但性能大致相同。

当您进入多GB解决方案时,一种选择是使用您自己管理的堆内存。 或者您可以使用像Zing这样的解决方案,它可以处理数十GB的堆而不会出现明显的暂停。