Java GC:为什么有两个幸存者空间[重复]

2023-11-24

在网上的大多数教程中,我们可以看到他们显示GC中有两个幸存者空间。 当我们实际上只能拥有一个幸存者空间时,为什么需要拥有两个呢? 拥有两个幸存者空间对性能有何影响?


原因是,你猜对了,性能。首先让我解释一下为什么幸存者空间存在。就基本问题而言,有两种主要的垃圾收集器设计对象重定位:

  • 就地压实集电极;

  • a copying集电极。

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

复制收集器的基本设计

注:下面是not对 HotSpot 实际 GC 的描述,而是 C.J. Cheney 在 1970 年 ACM 论文中提出的原始设计的那些方面。 HotSpot 添加了进一步的改进,其中之一是添加了Eden空间解释如下。

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

  • From space: a contiguous block of memory split into two regions:
    • 上次 GC 的幸存者;
    • 新对象(自上次 GC 之后创建的);
  • To空间:完全空旷。

GC运行的任务是识别内存中所有存活的对象From空格并将它们复制到To space.

As the To空间正在被建立起来,From空间将被完全清空,并且不需要向其中写入任何内容。

复制GC是单程

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

前向指针

当每个幸存的对象被重新定位时,旧位置可以用转发指针然后,当扫描幸存对象以查找对重新定位对象的引用并更新这些引用时,可以有效地使用此信息。旧的引用指向前向指针,因此只需一次查找即可获得新的指针值。

为什么是第三个空格?

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

HotSpot 推出了Edenspace 作为一种优化,可以保持新分配区域的容量不变,押注于结果是大部分对象将立即变成垃圾。你可以看看Eden作为记忆的一部分shared两个空间之间——可能会在下一次 GC 时释放的部分。这实际上提高了内存利用率。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java GC:为什么有两个幸存者空间[重复] 的相关文章

随机推荐