【JVM】—G1中的Young GC、Mixed GC、Full GC详解

G1中的Young GC、Mixed GC、Full GC详解

⭐⭐⭐⭐⭐⭐

Github主页👉https://github.com/A-BigTree

笔记链接👉https://github.com/A-BigTree/Code_Learning

⭐⭐⭐⭐⭐⭐

如果可以,麻烦各位看官顺手点个star~😊

文章目录

  • [G1中的Young GC、Mixed GC、Full GC详解](#G1中的Young GC、Mixed GC、Full GC详解)
    • [1 G1的GC模式](#1 G1的GC模式)
    • [2 Young GC](#2 Young GC)
    • [3 Mixed GC](#3 Mixed GC)
      • [3.1 Mixed GC发生时机](#3.1 Mixed GC发生时机)
    • [4 Full GC](#4 Full GC)

关于G1回收器的前置知识点:

1 G1的GC模式

G1提供了两种GC模式,Young GC和Mixed GC,两种都是完全Stop The World的。

  • Young GC:选定所有年轻代里的Region。通过控制年轻代的region个数,即年轻代内存大小,来控制young GC的时间开销。
  • Mixed GC:选定所有年轻代里的Region,外加根据Global concurrent marking统计得出收集收益高的若干老年代Region。在用户指定的开销目标范围内尽可能选择收益高的老年代Region。

由上面的描述可知,Mixed GC不是full GC ,它只能回收 部分 老年代的Region,如果mixed GC实在无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,就会使用serial old GC(full GC) 来收集整个GC heap。所以我们可以知道,G1是不提供full GC的

2 Young GC

Young GC垃圾回收过程中,分为以下几种情况:

  1. 新创建对象(非巨大对象)分配到Eden区;
  2. Eden区对象转移到幸存区;
  3. 幸存区对象转移到另一幸存区;
  4. 幸存区对象转移到老年代;

用几张图片解释Young GC流程:

  • 这里有 eden,survivor,old 还有个 free region,黄色为存活对象
  • G1会把橙色对象拷贝到free region,或转移到幸存或老年代
  • 当拷贝完毕,free region 就会晋升为 survivor region,以前的 eden 就被释放了

3 Mixed GC

Mixed GC会选取所有的 Young Region ➕ 收益高的若干个 Old Region。让我们回顾一下G1回收器工作过程(其实就是Mixed GC的过程),即我们上面一直提到的Global concurrent marking,一共分为四个步骤:

  1. 初始标记(initial mark,STW):它标记了从GC Root开始直接可达的对象。
  2. 并发标记(Concurrent Marking):这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。
  3. 最终标记(Remark,STW):标记那些在并发标记阶段发生变化的对象,将被回收。
  4. 清除垃圾(Cleanup):清除空Region(没有存活对象的),加入到free list。

同时值得注意的是,对于第一阶段的初始标记,Mixed GC是共用了Young GC的SWT,这是因为他们可以复用root scan操作,所以可以说Global concurrent marking操作是伴随Young GC而发生的。

具体执行过程如下图所示:

同样的,被回收的 Region 就变回 Free Region 了,从上图可以看到 Mixed GC 只能回收部分的老年代。

G1 是如何选择要回收的 regions 的?

  • -XX:G1MaxNewSizePercent 与 Young GC关联;
  • -XX:MixedGCCountTarget 与 Old GC关联;

-XX:MixedGCCountTarget默认是8,意味着要在8次以内回收完所有的 Old Region

  • 换句话说,如果对立有 800 个 old region, 那么一次Mixed gGC最大会回收 100 个 Old Region

G1 当然也可以被调整成不做这么多工作,也就是少回收,一定程度上浪费堆内存,导致更多的堆空间被使用

  • -XX:G1MixedGCLiveThresholdPercent (默认:85) 可能会提高堆使用率
  • -XX:G1HeapWastePercent (默认:5) 如果可回收低于这个值, 那么将不会启动Mixed GC

3.1 Mixed GC发生时机

Young GC发生的时机大家都知道(文章开头已表明),那什么时候发生Mixed GC呢?其实是由一些参数控制着的,另外也控制着哪些老年代Region会被选入CSet。

  • G1HeapWastePercent:在Global concurrent marking结束之后,我们可以知道老年代regions中有多少空间要被回收,在每次YGC之后和再次发生Mixed GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC;
  • G1MixedGCLiveThresholdPercent:老年代Region中的存活对象的占比,只有在此参数之下,才会被选入CSet。
  • G1MixedGCCountTarget:一次Global Concurrent marking之后,最多执行Mixed GC的次数;
  • G1OldCSetRegionThresholdPercent:一次Mixed GC中能被选入CSet的最多老年代 Region数量。

4 Full GC

由上面的描述可知,Mixed GC不是Full GC ,它只能回收部分老年代的Region,如果mixed GC实在无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,就会使用serial old GC(Full GC)来收集整个GC heap和方法区(元空间) 。所以我们可以知道,G1是没有 Full GC的机制的,G1 GC是使用的Serial Old GC的代码(后面被优化为多线程,但是速度相对来说依然比较慢),因此Full GC会暂停很久,因此在生产环境中,一定注意Full GC。

G1 Full GC的原因一般有:

  • Mixed GC赶不上内存分配的速度,只能通过Full GC来释放内存,这种情况解决方案后面再说
  • MetaSpace不足,对于大量使用反射,动态代理的类,由于动态代理的每个类都会生成一个新的类,同时class信息会存放在元空间,因此如果元空间不足,G1会靠Full GC来扩容元空间,这种情况解决方案就是扩大初始元空间大小。
  • Humongous分配失败,前面说过G1分配大对象时,回收是靠Concurrent MarkingFull GC,因此如果大对象分配失败,则可能会引发Full GC
相关推荐
阿龟在奔跑2 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉3 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉3 小时前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo3 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10221 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则
我是苏苏1 天前
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
java·前端·jvm
天草二十六_简村人1 天前
Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化
java·jvm·数据库·mongodb·阿里云·微服务·云计算
老码沉思录1 天前
Android开发实战班 - 数据持久化 - Room 数据库应用
android·jvm·数据库
起名字真南1 天前
【C++】深入理解 C++ 中的继承进阶:多继承、菱形继承及其解决方案
java·jvm·c++·chatgpt·aigc
偶尔。5351 天前
JVM垃圾回收算法详解
jvm