为什么必须在Eden空间中创建新的Java对象?

为什么必须在Eden空间中创建新的Java对象?,java,garbage-collection,jvm,Java,Garbage Collection,Jvm,Java垃圾收集对年轻对象使用副本收集器。年轻一代区域分为“伊甸园空间”和两个幸存者空间,s0和s1 据我所知,副本收集器将幸存对象从伊甸园和一个幸存者空间复制到另一个幸存者空间 从概念上讲,两个空间就足够了,将幸存者从一个空间复制到另一个空间。我假设Java使用3个空间而不是2个空间的原因是,新对象总是可以在同一个地方创建,在Eden区域 问题是为什么在伊甸园区域创建新的(年轻空间)对象很重要,而不是在“复制到”幸存者空间中的最后一个复制对象之后?您提出的备选方案有两个大小相等的新空间,并从一

Java垃圾收集对年轻对象使用副本收集器。年轻一代区域分为“伊甸园空间”和两个幸存者空间,s0和s1

据我所知,副本收集器将幸存对象从伊甸园和一个幸存者空间复制到另一个幸存者空间

从概念上讲,两个空间就足够了,将幸存者从一个空间复制到另一个空间。我假设Java使用3个空间而不是2个空间的原因是,新对象总是可以在同一个地方创建,在Eden区域


问题是为什么在伊甸园区域创建新的(年轻空间)对象很重要,而不是在“复制到”幸存者空间中的最后一个复制对象之后?

您提出的备选方案有两个大小相等的新空间,并从一个复制到另一个。当(总)新空间的一半被填满时,您会发现需要运行新一代GC

在Oracle GCs使用的方法中,其中(通常)Eden size>S1 size+S2 size,在运行新一代GC时,您已经填充了S1(或S2)的所有Eden+部分。这将大大超过新空间内存总量的一半。换句话说,新的空间内存被更有效地使用

本Oracle培训资料提供了一些很好的图表,解释了新一代和旧一代GC期间发生的情况:


但请注意,本教程描述的是一个简化的分代收集器。不同版本的Java支持的各种实际收集器的详细信息差别很大。

您建议的替代方案有两个大小相同的新空间,并从一个复制到另一个。当(总)新空间的一半被填满时,您会发现需要运行新一代GC

在Oracle GCs使用的方法中,其中(通常)Eden size>S1 size+S2 size,在运行新一代GC时,您已经填充了S1(或S2)的所有Eden+部分。这将大大超过新空间内存总量的一半。换句话说,新的空间内存被更有效地使用

本Oracle培训资料提供了一些很好的图表,解释了新一代和旧一代GC期间发生的情况:


但请注意,本教程描述的是一个简化的分代收集器。不同版本的Java支持的各种实际收集器的详细信息差别很大。

对于G1,只有一个幸存者空间(尽管为了兼容性,JVM报告存在两个空间)

使用G1收集器,所有堆都是单池,“功能”空间是完全动态的。因此幸存者空间只分配给收集(收集完成后成为伊甸园的一部分)


HotSpot JVM中支持的大多数其他收集器要求“功能”空间具有JVM启动时定义的静态边界。因此,空的幸存者空间不能成为eden的一部分。

对于G1,只有一个幸存者空间(尽管为了兼容性,JVM报告存在两个空间)

在G1收集器中,所有堆都是单池,“功能”空间是完全动态的。因此,幸存者空间只分配给收集(收集完成后成为eden的一部分)


HotSpot JVM中支持的大多数其他收集器需要“功能性”空间具有JVM启动时定义的静态边界。因此,空的幸存者空间不能成为eden的一部分。

谢谢。如果eden>S1+S2,S2中没有足够的可用空间来存储eden+S1幸存者不是很危险吗?如果死亡率高到足以避免这种情况,S3、S4等会进一步增加空间使用吗?如果1不够大,无法容纳幸存者,物品将被终身使用。谢谢。如果伊甸园>S1+S2,S2中没有足够的空间来存储伊甸园+S1幸存者,这不是有风险吗?如果死亡率高到足以避免这种情况,S3、S4等是否会进一步增加空间使用率?如果S1不够大,无法容纳幸存者,物品将是10个但是G1幸存者空间被分割成许多独立的区域,对吗?@GonenI和G1所有堆被分割成区域。虽然区域可以在某一点上是幸存者的一部分,在另一点上是eden或事件旧空间的一部分。但是G1幸存者空间被分割成许多独立的区域,对吗?@GonenI和G1所有堆被分割成区域。你gh区域可以是某点幸存者的一部分,也可以是另一点伊甸园或事件旧空间的一部分。“在幸存者空间的最后一个对象之后”是一个单一的位置。对于JVM来说没有帮助,在JVM中任意数量的线程都可以进行分配。因此,通常,每个线程从年轻一代获取一个TLAB,并且获取它们的区域称为Eden空间。这是否是真实的(具有不灵活的边界)或者只是一个逻辑名称,取决于特定的垃圾收集器。“在幸存者空间的最后一个对象之后”是一个单一的位置。对于JVM来说没有帮助,在JVM中任意数量的线程都可以进行分配。因此,通常,每个线程从年轻一代获取一个TLAB,并且获取它们的区域称为Eden空间。这是否是真实的(具有不灵活的边界)或者只是一个逻辑名称,取决于特定的垃圾收集器。