【问题标题】:JVM garbage collection in young generation年轻代中的 JVM 垃圾回收
【发布时间】:2012-12-01 15:30:45
【问题描述】:

如果我错了,请随时纠正我。在 JVM 堆中,有两代,老的和年轻的。在做full GC的时候,老年代,有紧凑空间、修复洞等繁重的操作,会导致JVM挂掉。而且我发现在年轻代中,应用了轻量级GC,从我的搜索结果中,还有一个叫做Eden的领域涉及年轻代。但是查了很多文档,对于young generation的GC,我还是有两个疑惑,

  1. 在年轻代中,似乎 GC 不像老一代 GC 那样工作(即老一代 GC 压缩并修复漏洞)?如果是这样,年轻代的 GC 是如何工作的?
  2. 什么是伊甸园空间,这个空间在年轻一代中是如何利用的?如果可以为新手推荐任何文档,请不胜感激。

【问题讨论】:

标签: garbage-collection jvm


【解决方案1】:

这是您必须记住和理解的唯一、最重要的图表:


(来源:oracle.com

它来自Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning,一站式了解 GC 内部原理。但要解决您的直接问题:

使用new 运算符(almost)分配新对象总是发生在伊甸园空间中。但伊甸园实际上是一个堆栈。当您创建需要 N 个字节的新对象时,单个指针在该堆栈上前进 N 个字节,仅此而已。分配就是这么快,无需搜索空闲位置、压缩等。

当然这个堆栈不是无限的,在某个时候我们会到达它的尽头,触发小 GC。也很可能多个对象已经是垃圾。那么JVM在minor GC中的作用如下:

  • GC 根开始的对象遍历图

  • 将所有可从 GC 根到达的对象复制到幸存者空间之一(没有间隙,我们知道所有这些对象,这是一个单一的过程)

  • 清除伊甸园空间(基本上只是将此堆栈指针移回0

在后续的次要集合中还有额外的步骤:

  • 还检查​​了幸存者空间之一。来自伊甸园和幸存者空间之一的活动对象被复制到第二个幸存者空间。这意味着始终只有一个空闲的幸存者空间。

那么对象是如何在tenured generation结束的呢?第一个年轻对象被复制到幸存者空间之一。然后它们被一次又一次地复制到另一个。一旦给定的对象来回跳转太多次(可配置,默认为 8 次),它就会被提升为永久空间。

Major GC 在永久空间已满时运行。

【讨论】:

  • 谢谢,托马斯。还有两个问题。 1.年轻代GC是如何触发的?基于固定时间间隔,或者当伊甸园空间用完,或更复杂的条件? 2. 对于您的评论,“一旦这种来回跳跃结束,他们将被提升到终身空间。”,“来回跳跃”过程将在什么情况下结束?根据您的描述,我们似乎总是可以像一个无止境的过程一样复制和强制?
  • @LinMa:我澄清了我的答案。当 eden 满时触发 Minor GC。任期满时的专业。如果对象从一个幸存者复制到另一个幸存者 8 次,则它们会从幸存者提升为终身。
  • 谢谢,托马斯。 1.您提到“从GC根开始的对象遍历图”,我认为您的意思是在伊甸园中遍历对象? 2.老年代的空闲空间不会被程序的new分配直接使用,只会被年轻代提升到老年代的对象使用?
  • @LinMa: 1.tenured 对象也被遍历,例如因为它们可以在年轻代中引用返回对象。但他们没有被触动。 2. 有时objects are allocated directly in old generation
  • 感谢 Tomasz,非常酷的链接,许多想法从未在其他文档中找到。您提到“将所有可从 GC 根到达的对象复制到幸存者空间之一”,1. 我认为在上下文中您的意思是将所有对象从伊甸园复制到幸存者空间之一? 2.当复制到幸存空间时,我们如何知道将对象放在幸存空间的什么位置?由于我认为年轻代的minor GC只标记一个对象是空闲还是使用而不做compaction,所以survivor空间中没有连续的空闲空间?如果是这样,在哪里决定将对象复制到幸存者空间的哪个位置?
猜你喜欢
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多