对于Sun/Oracle的JVM,我读到GC算法将新一代划分为一个Eden区域和两个幸存者区域。我想知道的是,为什么是两个幸存者区域而不仅仅是一个?该算法可以在Eden和一个幸存者区域之间保持乒乓声(目前在两个幸存者区域之间的方式);或者这种方法有什么缺点吗?
我相信JRockit的GC实现更像你建议的那样工作,只有一个伊甸园和一个幸存者空间,但不要引用我的话。
HotSpot JVM有两个幸存空间的原因是为了减少处理碎片的需要。在eden空间中分配新对象。一切都很好。当它满了,你需要一个GC,所以杀死过时的对象,将活的对象移到一个幸存者空间,在那里它们可以成熟一段时间,然后再升级到老一代。到目前为止还不错。然而,下一次当我们耗尽伊甸园空间时,我们就遇到了一个难题。下一个GC出现并清除了eden和我们的幸存者空间中的一些空间,但这些空间不是连续的。那么
孙对这个问题的回答是显而易见的。
在一个小型垃圾回收机制运行后,两个幸存者空间的角色发生了逆转
两个幸存者空间。这些对象至少在一次小垃圾收集中幸存下来,但在升级到旧一代之前又有一次机会无法访问。其中只有一个保存对象,而另一个大部分时间未使用。
在小垃圾收集操作期间,被发现是垃圾的对象将被标记。在收集中幸存下来的eden中的活对象被复制到未使用的幸存者空间。正在使用的幸存者空间中的活对象也被复制到未使用的幸存者空间中,这些活对象将在年轻一代中被给予另一次回收的机会。最后,正在使用的幸存者空间中被认为“足够老”的活对象被提升到老一代。
在次要垃圾回收结束时,两个幸存者空间交换角色。伊甸园完全是空的;只有一个幸存者空间在使用中;而老一辈的入住率略有增长。由于活动对象在其操作过程中被复制,因此这种类型的垃圾回收器称为复制垃圾回收器。
来源:以上是查理·亨特和比努·约翰 Java 表演第83页的摘录。
年轻一代:这是短暂居住的地方,分为两个空间:
伊甸园空间:新的对象将被分配到内存池中。假设大多数对象在创建后不久就被取消引用并变得不可访问。未被解引用的对象将被新一代垃圾收集器复制到幸存者空间中。在某些特殊情况下,它们可能会被直接复制到老一代池中。
幸存者空间:这两个小空间保存着年轻一代垃圾收集的幸存物品。幸存的物体将被从一个幸存者复制到另一个幸存者的(少量)次数。这允许收获我们更多取消引用的对象。
老一代:应该保存长寿命对象的最大内存池。一旦对象离开幸存者空间,它们就被复制到这个池中。
永久生成:这个相当未知的池保存所有类的信息。对于大多数应用程序来说,它不需要任何关注。它可能需要适应一些具有许多类的应用程序。如果应用程序永久加载和卸载类,它可能也需要一些关注。
其他优势:
请查找以下链接以了解更多详细信息,帮助您了解更多信息
http://www.scalingbits.com/javaprimer
http://java.sys-con.com/node/84695