原创

JVM实战(4)——理论基础篇: Minor、Major 和 Full GC

温馨提示:
本文最后更新于 2023年07月19日,已超过 490 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

一、概念

1.1、新生代收集(Minor GC/Young GC)

只针对新生代的垃圾收集。具体点的是Eden区满时触发GC。Survivor满不会触发Minor GC。

1.2、老年代收集(Major GC/Old GC)

只针对老年代的垃圾收集。目前,只有CMS收集器会有单独收集老年代的行为。注意,很多时候,Major GC 会和Full GC混淆使用,需要具体分辨是老年代的回收还是整堆回收。

1.3、混合收集(Mixed GC)

指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。

1.4、整堆收集(Full GC)

收集整个Java堆和方法区的垃圾收集。

二、详细说明

2.1、Minor GC

当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。所以分配率越高,越频繁执行 Minor GC。

内存池被填满的时候,其中的内容全部会被复制,指针会从0开始跟踪空闲内存。Eden 和 Survivor 区进行了标记和复制操作,取代了经典的标记、扫描、压缩、清理操作。所以 Eden 和 Survivor 区不存在内存碎片。写指针总是停留在所使用内存池的顶部。

执行 Minor GC 操作时,不会影响到永久代。从永久代到年轻代的引用被当成 GC roots,从年轻代到永久代的引用在标记阶段被直接忽略掉。

对于大部分应用程序,Minor GC 操作时应用程序停顿导致的延迟都是可以忽略不计的。因为,大部分 Eden 区中的对象都能被认为是垃圾,永远也不会被复制到 Survivor 区或者老年代空间。如果正好相反,Eden 区大部分新生对象不符合 GC 条件,Minor GC 执行时暂停的时间将会长很多。

 

2.2、Major GC

目前,只有CMS收集器会有单独收集老年代的行为。其他收集器均无此行为。

针对新生代(主要指Eden区)的Minor GC 比较常见,各个收集器均支持。

通常能单独发生收集行为的只是新生代的Minor GC,所以这里“反过来”的情况只是理论上允许,实际上除了CMS收集器,其他都不存在只针对老年代的收集。

 

2.3、Full GC

当年老代满时会引发Full GC,Full GC将会同时回收新生代、老年代 ;当永久代满时也会引发Full GC,会导致Class、Method元信息的卸载 。

如果超过 98% 的总时间花费在垃圾回收上,并且回收的堆少于 2%,则抛出 , OutOfMemoryError。此功能旨在防止应用程序因堆太小而长时间运行而几乎没有进展或没有进展。如有必要,可以通过将选项添加-XX:-UseGCOverheadLimit到命令行来禁用此功能。

注:该OutOfMemoryError规则查看Java SE 6\8\18 的描述均相同,所以,可以推断基本适用于所有的JVM。

三、触发条件

3.1、Minor GC触发条件

当年轻代(Eden区)满时就会触发 Minor GC,这里的年轻代满指的是 Eden区满。Survivor 满不会触发 Minor GC 。

3.2、Major GC触发条件

CMS收集器中,当老年代满时会触发 Major GC。

3.3、Full GC触发条件

3.3.1、主动触发

(1)调用System.gc()或Runtime.getRuntime().gc()者时,系统建议执行Full GC,但是不一定会执行 。

(2)执行jmap命令。

(3)通过jcmd命令,如: jcmd 7544 GC.run

3.3.2、被动触发

(1)新生代对象熬过N=15次垃圾回收,晋级到老年代,老年代可用连续内存不足

(2)由Eden区、S0(或S1)区向 S1(或S0)区复制时,对象大小大于To Space可用内存,则把该对象直接转存到老年代,老年代可用连续内存不足

(3)永久代空间不足

(4)永久代PermGen发生扩展,如配置了-XX:PermSize  -XX:MaxPermSize参数值

(5)老年代内存使用率超过一定比例,直接触发Old GC(注:有文档参考的只有CMS和G1垃圾回收器

四、扩展及资料补充

上面提到的老年代内存使用率超过一定比例触发Full GC的情况,仅在CMS和G1垃圾回收器的文档中有说明,而且也不是直接描述,是通过”启动并行回收周期(Starting a Concurrent Collection Cycle)“进行说明的。在CMS和G1的描述中,也不尽相同。而对于Java SE 8中默认的Parallel GC则没有此部分。

4.1、CMS关于Starting a Concurrent Collection Cycle的描述(Java SE 6&8)

该比例默认值为92%,设置参数为:-XX:CMSInitiatingOccupancyFraction=<N>

4.2、G1关于Starting a Concurrent Collection Cycle的描述(Java SE 8)

该比例默认值为45%,设置参数为:-XX:InitiatingHeapOccupancyPercent=<NN>

4.3、参考文档

Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning

Java SE 8: Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide

HotSpot Virtual Machine Garbage Collection Tuning Guide

正文到此结束
本文目录