-
Eden区满了,会触发minor gc,所有存活的对象会拷贝到Survivor区域,年龄增加“1”,然后清空Eden区。
-
再次触发minor gc,会将Eden和Survivor 1 区域中存活的对象移到Survivor 2中,年龄加”1”,然后清空Eden和Survivor 1 区域。
-
再次触发minor gc,年龄最够大(JVM设置)机会升级到Tenured区域。
-
再次触发minor gc,又有对象升级到Tenured区域,但是Tenured区域没有空间容纳新的对象,就会触发年老代上的垃圾回收,称为major gc。
-
major gc取决于使用哪种垃圾回收算法:
- Parallel Scavenge(PS)
- Concurrent Mark Sweep(CMS)
-
发生major gc后,会采用标记-清除算法回收所有非可到达对象。
-
因为步骤1容易产生内存碎片,所以再采用标记-压缩算法来消除内存碎片。
采用标记-清除算法(与PS不同,有4个阶段),应用程序是可以并行运行的:
-
Initial Mark 阶段 - 短暂的Stop-The-World,标记根对象的第一层孩子节点。
-
Concurrent Mark 阶段 - 以标记的节点为根对象,重新开始标记Tenured区域的可达对象。程序在此阶段是继续运行的。
-
Remark 阶段 - 短暂的Stop-The-World,确保新加入Tenured对象有被标记到,采用多线程加速。
-
Concurrent Sweep阶段 - 清除。
但是很不幸的是,CMS垃圾收集器虽然减少了暂停应用程序的运行时间,但是由于它没有Compact阶段,它还是存在着内存碎片问题。于是,为了去除内存碎片问题,同时又保留CMS垃圾收集器低暂停时间的优点,JAVA7发布了一个新的垃圾收集器 - G1垃圾收集器。它会在未来逐步替换掉CMS垃圾收集器。
G1垃圾收集器和CMS垃圾收集器有几点不同。首先,最大的不同是内存的组织方式变了。Eden,Survivor和Tenured等内存区域不再是连续的了,而是变成了一个个大小一样的region - 每个region从1M到32M不等。
一个region有可能属于Eden,Survivor或者Tenured内存区域。图中的E表示该region属于Eden内存区域,S表示属于Survivor内存区域,T表示属于Tenured内存区域。图中空白的表示未使用的内存空间。G1垃圾收集器还增加了一种新的内存区域,叫做Humongous内存区域,如图中的H块。这种内存区域主要用于存储大对象-即大小超过一个region大小的50%的对象。
在G1垃圾收集器中,年轻代的垃圾回收过程跟PS垃圾收集器和CMS垃圾收集器差不多,新对象的分配还是在Eden region中,当所有Eden region的大小超过某个值时,触发minor gc,回收Eden region和Survivor region上的非可达对象,同时升级存活的可达对象到对应的Survivor region和Tenured region上。对象从Survivor region升级到Tenured region依然是取决于对象的年龄。
对于年老代上的垃圾收集,G1垃圾收集器也分为4个阶段,基本跟CMS垃圾收集器一样,但略有不同:
-
Initial Mark阶段 - 同CMS垃圾收集器的Initial Mark阶段一样,G1也需要暂停应用程序的执行,它会标记从根对象出发,在根对象的第一层孩子节点中标记所有可达的对象。但是G1的垃圾收集器的Initial Mark阶段是跟minor gc一同发生的。也就是说,在G1中,你不用像在CMS那样,单独暂停应用程序的执行来运行Initial Mark阶段,而是在G1触发minor gc的时候一并将年老代上的Initial Mark给做了。
-
Concurrent Mark阶段 - 在这个阶段G1做的事情跟CMS一样。但G1同时还多做了一件事情,那就是,如果在Concurrent Mark阶段中,发现哪些Tenured region中对象的存活率很小或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,而不用等到后面的clean up阶段。这也是Garbage First名字的由来。同时,在该阶段,G1会计算每个 region的对象存活率,方便后面的clean up阶段使用 。
-
Remark阶段 - 在这个阶段G1做的事情跟CMS一样, 但是采用的算法不同,G1采用一种叫做SATB(snapshot-at-the-begining)的算法能够在Remark阶段更快的标记可达对象。
-
Clean up/Copy阶段 - 在G1中,没有CMS中对应的Sweep阶段。相反 它有一个Clean up/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进行回收,这个阶段也是和minor gc一同发生的,如下图所示:
从上可以看到,由于Initial Mark阶段和Clean up/Copy阶段都是跟minor gc同时发生的,相比于CMS,G1暂停应用程序的时间更少,从而提高了垃圾回收的效率。