【问题标题】:What is the purpose of Survivor Space in Java memory?Java 内存中 Survivor Space 的用途是什么?
【发布时间】:2020-08-15 22:09:52
【问题描述】:

尝试查找此内容,但我遇到的所有问题/答案都是关于拥有 2 个幸存者空间的目的。我想了解一般拥有幸存者空间的目的。将物体从 Eden 移动到 Survivor 有什么好处?

【问题讨论】:

  • @Ivan 应该是重复的,但不幸的是,它的答案都没有真正回答这个问题。
  • @OrangeDog 我认为对该问题的投票最多的答案也适合这个问题。这个问题说明了为什么有 3 种类型的空间,而这个问题询问是否存在这 3 种类型中的一种
  • @Ivan 不,没有一个答案提到有三个,更不用说解释了。

标签: java memory-management garbage-collection jvm jvm-hotspot


【解决方案1】:

性能

一般来说,拆分堆(无论是分代还是任何其他鉴别器)被认为是一件相当不错的事情,但并非所有收集器都遵循这一点(例如,Shenandoah 不是这样的收集器)。

为什么这是好事?扫描整个堆以查找活动对象需要时间。你如何告诉你的垃圾收集器——“现在该运行了”。 那个时间是什么时候?你可以说:在每 100 个分配的对象之后运行。是不是太快了? (如果这些对象的大小只是堆的一小部分怎么办)或更糟:是否为时已晚?如果您说:在堆占用率的 65% 处触发收集(G1 在该百分比下触发主要收集,以及其他可能性,默认情况下)。如果在这 65% 中,您发现大部分对象应该更早地被收集,但它们在堆中停留的时间太长了。

您可以看到这很快变得复杂。当您了解扫描堆需要时间时,情况会变得更糟,而您最不希望的事情是让您的应用程序在 GC 运行时停止。但也请记住,有些收集器会同时扫描堆,所以他们没有这个问题(ShenandoahZGCC4)。

如果可以分离堆,则可以只扫描其中的一部分,从而花费很少的时间。人们称它们为“次要”收藏。一些收集器因此将堆划分为“年轻”和“老”,这种划分是基于“婴儿死亡率”的前提:年轻的对象死得很快。因此,如果您进行这种分离+年轻对象很快就会死亡,您只能扫描堆的特定部分,并且在大多数情况下只处理它。这也简化了以下问题的答案:GC 应该何时运行?当然,年轻时已经饱了。

现在直奔主题:为什么需要幸存者。让我们假设它不存在。第一个 GC 周期发生(年轻区域已满,准确地说,我们称之为 Eden),接下来会发生什么? GC 需要知道那里还活着的东西,把它移到“老年代”,清除Eden 并重新开始分配。第二个周期进来并做同样的事情,依此类推,直到 GC 说:“如果老一代满了,我就不能再移动了”。这是著名的“老一代”发生的地方。这通常很昂贵。

但我们确实了解这里的“婴儿死亡率”。我们确实知道第二次和第三次 GC 循环将一些对象移到了老年代,这些对象本应在第四阶段收集。错过了这个机会。因此:幸存者空间。它将对象在其中保留“稍长一点”,然后是一个 GC 周期(称为幸存者年龄),知道在最近的将来这将成为垃圾。因此,无需经常扫描旧的,只需扫描并处理堆的 较小 部分(EdenSurvivor)。至于为什么有两个幸存者空间,这是一个单独的问题......

实际上,最新的 GC 不需要这个。他们找到了一种在您的应用程序运行时同时扫描堆的方法,因此他们没有这些空间。年轻死亡的前提仍然存在,一些 GC 算法可能会使用它;现在或将来。

【讨论】:

  • 感谢您的回答,尤金。进一步说,它将对象在其中保留“稍长一点”:假设没有Survivor spaceEden 将分配更大的内存空间。这应该会导致在触发次要 GC 之前将对象保留更长时间。那么Survivor space 将如何更好地保持对象“更长一点”?
  • @dj_rai 压缩。如果你这样做,你的Eden 会看起来像瑞士国际象棋:里面有洞。您很快就会陷入无法再分配对象的情况,因为没有连续的空间并且需要进行“碎片整理”。 Survivor 空间通过 复制 对象解决了这个问题,因此在下一个循环中,Eden(和一个 Survivor 空间)为空。
  • “老化”策略也可以在单个伊甸园内实施。幸存的对象可以移动到 Eden 空间的开头(就像在老一代中压缩的工作方式一样)。但是与复制到始终为空的空间相比,实现压缩有点困难,并且需要更多时间。所以,Survivor 是一种优化,它用一点堆空间来换取更快、更简单的年轻集合。
  • @dj_rai 是的,只有 2 个幸存者空间(并且没有伊甸园)也是可能的,但意味着更大的内存浪费(50% 的年轻一代)。除了 eden 外还有 2 个小的幸存者空间,内存浪费通常是年轻代的 12.5% 左右,性能水平相同。
  • @dj_rai 请注意,旧的垃圾回收实现具有更严格的内存组织。对于像 G1GC 这样动态地将内存块分配给这些空间的实现,您是否将 Eden 和非空生存空间视为单个源实体并不重要。在复制过程中,它们只是源,但在分配时,前一个集合的目标幸存者空间的内存块被对象占用,因此无法使用,因此您可以区分它们来自可以用新对象填充的块(伊甸园空间的一部分)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2011-02-22
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
相关资源
最近更新 更多