Java GC:为什么两个幸存者区域?

时间:2012-05-22 03:17:05

标签: java garbage-collection jvm

对于Sun / Oracle的JVM,我读过GC算法将新一代划分为一个伊甸园区域和两个幸存区域。我想知道的是,为什么两个幸存者地区而不仅仅是一个?算法可以在伊甸园和一个幸存者区域之间保持乒乓(目前两个幸存者区域之间的方式);或者这种方法有什么缺点吗?

8 个答案:

答案 0 :(得分:72)

我相信JRockit的GC实现更像你的建议,只有一个伊甸园和单个幸存者空间,但不要引用我。

HotSpot JVM的两个幸存者空间的原因是减少了处理碎片的需要。新对象在eden空间中分配。一切都很好。当它已满时,你需要一个GC,所以杀死过时的对象并将活动对象移动到幸存者空间,在升级到老一代之前,它们可以成熟一段时间。到目前为止仍然很好。但是,下次我们用完伊甸园空间时,我们就有了一个难题。下一个GC出现并清除了伊甸园和幸存者空间中的一些空间,但这些空间并不是连续的。

更好
  1. 试着让伊甸园的幸存者进入幸存者空间中被GC清除的洞?
  2. 将幸存者空间中的所有对象向下移动以消除碎片,然后将幸存者移入其中?
  3. 只要说“搞砸它,我们无论如何都要移动所有东西”,并将所有幸存者从两个空间复制到一个完全独立的空间 - 第二个幸存者空间 - 从而留下一个干净的伊甸园和幸存者空间你可以在下一个GC上重复序列吗?
  4. 太阳对这个问题的回答是显而易见的。

答案 1 :(得分:21)

在小型垃圾收集操作后,两个幸存者空间的角色被颠倒

两个幸存者空间。这些对象保留了至少一个小的垃圾收集幸存的对象,但在升级到老一代之前又被给予了另一个无法访问的机会。其中只有一个持有物体,而另一个持有物体 未使用。

在小型垃圾收集操作期间,将标记已发现为垃圾的对象。在集合中存活的伊甸园中的活物体被复制到未使用的幸存者空间。正在使用的幸存者空间中的活物体将被给予另一个在年轻一代中被回收的机会,也被复制到未使用的幸存者空间。最后,在被使用的幸存者空间中的活物体被认为是 “够老了,”被提升为老一代。

在次要垃圾收集结束时,两个幸存者空间交换角色。伊甸园完全是空的;只有一个幸存者空间正在使用中;老一代的入住率略有增长。由于活动对象在其操作期间被复制,因此这种类型的垃圾收集器称为复制垃圾收集器。

来源:以上是Charlie Hunt和Binu John撰写的 Java Performance 第83页摘录。

答案 2 :(得分:3)

年轻一代:这是短期居住的地方,分为两个空间:

Eden space:新对象将在内存池中分配。假设大多数对象在创建后很快被取消引用并且无法访问。未被解除引用的对象将被新一代垃圾收集器复制到幸存者空间中。他们可能会被某些特殊情况直接复制到旧一代池中。

幸存者空间:这两个小空间保留了年轻一代垃圾收集的幸存对象。幸存物体将从一个幸存者复制到另一个幸存者(小)次。这允许收获我们更多的解除引用的对象。

老一代:应该保留长生命对象的最大内存池。一旦它们离开幸存者空间,对象就会被复制到这个池中。

Permament generation:这个相当未知的池保存所有类的信息。对于大多数应用程序,它不需要任何关注。它可能需要适用于具有许多类的一些应用程序。如果应用程序永久加载和卸载类,则可能需要一些注意。

其他优点:

  • 内存碎片
  • 提高GC性能

请查看以下链接以获取更多详细信息,以帮助您了解更多信息

http://www.scalingbits.com/javaprimer

http://java.sys-con.com/node/84695

答案 3 :(得分:2)

所有当前的答案都谈到了内存碎片,这也是GC中有几代人的另一个原因。

运行时记录指向“新对象”的所有“旧对象”,每次更新“指针”字段时都会执行此操作。然后,当“矿工”GC完成时,只需要扫描“新”对象。

多年来,人们发现仅仅拥有“新”和“旧”是不够的,拥有第三代“中年”是件好事。

答案 4 :(得分:1)

将一代的所有实例从一个空间复制到另一个空间有什么优点和缺点,而不是将它们以内存地址顺序复制到一代空间的开头?按顺序处理项目可能需要为每个项目添加额外的指针,但不需要其中一个“幸存者”空间。

答案 5 :(得分:0)

两名幸存者正在实施标记和复制算法。这些用于年轻一代的GC。正如Ryan在选项3 here

中所提到的那样

enter image description here

答案 6 :(得分:0)

Java中的堆内存 在称为堆内存的区域中创建的Java对象。堆内存在JVM启动时创建,堆内存在运行java应用程序时增加或减少。当堆内存变满时,垃圾收集器会删除未使用的对象,因此垃圾收集器会为新对象腾出空间。

堆内存分为两个区域(或几代),称为

1.年轻的空间。 2.old space。

1.在年轻的空间中,有新的物体的伊甸园空间,有两个幸存者空间(从和到),这两个幸存者空间总是相同的大小。

2.Survivor Spaces用于存储生存对象。当年轻空间变满时,垃圾收集器通过运行一个特殊的年轻集合来移除未使用的对象,其中所有在年轻空间中生活足够长的对象都被提升(移动) )到旧空间,从而释放年轻空间以进行更多的物体分配。

3.如果伊甸园空间已满,GC将运行,如果此伊甸园空间中有任何物体,则将其移至幸存者空间。

4.在年轻的空间中,GC通常使用复制算法,这是快速的,每次,生存对象都被复制到一个幸存者空间。

5.如果Survivor Space已满,其余的实时对象将直接复制到旧空间。

6.在旧空间中,GC非常使用Mark-Compact算法,这种算法很慢但需要的内存较少。

7.当旧空间变满时,会在那里收集垃圾,这个过程称为旧集合。在旧空间中,物体停留在那里很长时间。

8.Out of Memory会发生新的Object甚至没有为OLD或Perm部件完成GC的空间。

9.在垃圾收集期间移动对象:eden - >幸存者 - >终身(旧空间)

答案 7 :(得分:-1)

物体在年轻一代的伊甸园开始他们的旅程。当Eden填满时,将执行次要GC:停止所有应用程序线程(停止世界暂停),丢弃不再使用的对象,并将来自Eden的所有其他对象移至第一个Survivor空间(S0 )。下次执行次要GC时,对象将从S0移到第二个Survivor空间(S1)。来自伊甸园的所有活动物体也都进入S1。请注意,这导致幸存者空间中不同的老化对象–我们有来自伊甸园的对象和已经存在于幸存者空间中的对象。次要GC的下一次迭代会将对象从S1移回到S0,因此Survivor空间会切换每个GC。为什么我们有两个幸存者空间,为什么我们要切换它们?非常简单-当对象达到一定的年龄阈值时,它就会升格为“老一代”。导致幸存者空间碎片化,可以通过将所有对象从S0移到S1并返回每个次要GC来轻松消除。