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

2022-08-31 12:16:07

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


答案 1

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

HotSpot JVM的两个幸存者空间的原因是减少处理碎片化的需要。在伊甸园空间中分配新对象。都很好,很好。当它满了,你需要一个GC,所以杀死陈旧的物体,把活着的物体移动到幸存者空间,在那里它们可以成熟一段时间,然后被提升到老一代。到目前为止还是不错的。然而,下次我们用完伊甸园空间时,我们有一个难题。下一个GC出现并清除了伊甸园和我们的幸存者空间中的一些空间,但这些空间并不连续。那么,最好是

  1. 尝试将伊甸园的幸存者装入由GC清除的幸存者空间中的洞中?
  2. 将幸存者空间中的所有物体向下移动以消除碎片,然后将幸存者移入其中?
  3. 只要说“搞砸了,我们无论如何都要移动所有东西”,然后将两个空间中的所有幸存者复制到一个完全独立的空间 - 第二个幸存者空间 - 从而给你留下一个干净的伊甸园和幸存者空间,你可以在下一个GC上重复这个序列?

孙中山对这个问题的回答是显而易见的。


答案 2

两个幸存者空间的作用在小型垃圾回收操作后被逆转

两个幸存者空间。这些对象在至少一次次要垃圾回收中幸存下来,但在晋升为老一代之前,又有一次机会变得无法访问。其中只有一个保存对象,而另一个则大部分时间未使用。

在运行次要垃圾回收期间,将标记已发现为垃圾的对象。在集合中幸存下来的伊甸园中的活体对象将被复制到未使用的幸存者空间。幸存者空间中正在使用的活体物体,将在年轻一代中再次获得回收的机会,也会被复制到未使用的幸存者空间中。最后,幸存者空间中正在使用的、被认为“足够老”的活体物体被提升到老一代。

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

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