java - Java内存中Survivor Space的目的是什么?

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

试图寻找这个,但我遇到的所有问题/答案都在谈论拥有 2 个幸存者空间的目的。我想了解一般来说拥有幸存者空间的目的。将物体从伊甸园移动到幸存者有什么好处?

最佳答案

表现。
一般来说,拆分堆(无论是分代还是任何其他鉴别器)被认为是一件相当好的事情,但并非所有收集器都遵循这一点(例如 Shenandoah 不是这样的收集器)。
为什么这是好事?扫描整个堆中的 Activity 对象需要时间。你如何告诉你的垃圾收集器 - “现在就开始运行”。那是什么时候?你可以说:在每 100 个分配的对象之后运行。是不是太快了? (如果这些对象的大小只是堆的一小部分怎么办)或更糟:是否为时已晚?如果您说:在堆占用率的 65% 时触发收集(G1 会在该百分比下触发主要收集,以及其他可能性,默认情况下)。如果在 65% 时您发现大部分对象应该更早地被收集,它们在堆中停留的时间太长了怎么办。
你可以看到这很快变得复杂。当您了解扫描堆需要时间时,情况会变得更糟,而您最不希望看到的就是应用程序在 GC 运行时停止运行。但也请记住,有一些收集器同时扫描堆,所以他们没有这个问题( ShenandoahZGCC4 )。
如果可以分离堆,则可以只扫描其中的一部分,从而花费很少的时间。人们称它们为“次要” Collection 。一些收集器因此将堆划分为“年轻”和“老”,这种分离是基于“婴儿死亡”的前提:年轻的对象死得很快。因此,如果您进行这种分离 + 年轻对象很快就会死亡,您只能扫描堆的特定部分,并且在大多数情况下只处理该部分。这也简化了以下问题的答案:GC 应该何时运行?年轻的时候当然是满的。
现在直接点:为什么需要幸存者,根本。让我们假设它不存在。第一个 GC 周期发生(年轻区域已满,我们准确地称其为 Eden),接下来会发生什么? GC 需要告诉那里什么是活着的,把它移到“老年代”,清除 Eden并重新开始分配。第二个循环进入并做同样的事情,依此类推,直到 GC 说:“如果老年代满了,我就不能再移动了”。这是著名的“老一代”发生的地方。它通常很昂贵。
但我们确实知道这里的“婴儿死亡率”。我们确实知道第二次和第三次 GC 周期将一些对象移动到了在第四阶段收集的老年代。错过了这个机会。因此:幸存者空间。它将对象在那里保留“更长的时间”,然后是一个单一的 GC 周期(称为幸存者年龄),知道在不久的将来这将成为垃圾。因此,不需要经常扫描旧的,只需扫描和处理堆的一小部分( EdenSurvivor )。至于为什么有两个幸存者空间,这是一个单独的问题......
实际上,最新的 GC 不需要那个。他们找到了一种在您的应用程序运行时同时扫描堆的方法,因此他们没有这些空间。年轻死亡的前提仍然存在,一些 GC 算法可能会使用它;现在或将来。

关于java - Java内存中Survivor Space的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63431251/

相关文章:

JSF 表中的 JavaScript 错误

java - 预期为 BEGIN_ARRAY,但使用改造和 Gson 在第 1 行第 1 列路径处为 STRING

c++ - 参数 : Where are they declared?

.net - .net中非静态类中静态变量的内存分配

java - 是否可以在启动 Activity 之前释放内存?

Java - int 值 1 与 2,147,483,647 的内存分配

ios - CGBitmapContextCreate 内存释放责任

java - 方法运行完成后是否收集局部变量

java - G1GC GC logs 是什么意思?

java - 使用 wifi 发现移动设备