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

时间:2019-09-19 15:48:56

标签: java garbage-collection jvm

Java垃圾收集将复制收集器用于年轻对象。青年一代地区分为“伊甸园空间”和两个幸存者空间,即s0和s1。

我了解到,副本收集器将幸存的对象从伊甸园和一个幸存者空间复制到另一个幸存者空间。

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

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

2 个答案:

答案 0 :(得分:2)

您提出的替代方案有两个相等大小的新空格,然后从一个空格复制到另一个空格。当(全部)新空间的一半被填满时,您将需要运行新一代的GC。

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

此Oracle培训材料具有一些不错的图表,它们解释了新一代GC和旧式GC期间发生的情况:

但是请注意,本教程描述的是简化的世代收集器。在Java不同版本支持的各种 actual 收集器中,详细信息差异很大。

答案 1 :(得分:2)

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

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

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