Java GC:为什么有两个幸存者空间

时间:2014-01-31 09:22:57

标签: java performance garbage-collection

在大多数在线教程中,我们可以看到它们显示GC中有两个幸存者空间。 当我们实际上只有一个时,需要有两个幸存者空间? 拥有两个幸存者空间会对绩效产生什么影响?

1 个答案:

答案 0 :(得分:24)

原因是,你猜对了,表现。让我首先解释为什么存在幸存者空间。关于对象重定位的基本关注点,有两种主要的垃圾收集器设计:

  • 就地压缩收集器;

  • 复制收藏家。

复制收集器可以更快地运行并且可以有效地并行化,主要是因为它永远不会覆盖任何对象。如果不使用一个“活动”和一个“休眠”堆空间,在每次GC运行后这两个切换角色都无法实现。

复制收集器的基本设计

注意:以下内容描述HotSpot的实际GC,而是它的那些方面,它们是C.J. Cheney在1970年ACM论文中提出的原始设计的一部分。 HotSpot增加了进一步的改进,其中一个是添加了下面解释的 Eden 空间。

当复制收集过程开始时,涉及两个空格:

  • 来自空间:一个连续的内存块分为两个区域:
    • 上一次GC的幸存者;
    • 新对象(自上次GC以来创建);
  • 空间:完全为空。

GC运行的任务是识别 From 空间中所有幸存的对象,并将它们复制到 To 空间。

在构建 To 空间时, From 空间将完全撤离,无需写入任何内容。

复制GC是单次传递

复制收集器的一个关键优势是它是单通道的:我们只扫描所有GC根,复制所有这些对象,然后扫描这些对象以进一步引用,复制所有指示对象。我们从不重新访问任何对象,也不需要任何支持内存结构。 (看 here对此有一个很好的解释。)

转发指针

当重新定位每个幸存对象时,可以使用转发指针标记旧位置,然后可以有效地使用此信息,因为扫描幸存对象以查找对重定位对象的引用,以及参考更新。旧引用指向前向指针,因此新指针值只是一次查找。

为什么是第三个空间?

你的问题,“为什么有两个幸存者空间?”实际上更好的措辞,“为什么一个单独的 Eden 空间?”。

HotSpot引入了 Eden 空间作为优化,使新分配区域的容量保持不变,并且投注大部分对象将立即变成垃圾的结果。您可以将 Eden 看作两个空格之间的内存共享的一部分 - 可能会在下一个GC上释放的部分。这实际上提高了内存利用率。