侧边栏壁纸
博主头像
月伴飞鱼 博主等级

行动起来,活在当下

  • 累计撰写 126 篇文章
  • 累计创建 31 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
JVM

JVM 中一次完整的 GC 流程是怎样的?

月伴飞鱼
2025-03-22 / 0 评论 / 1 点赞 / 12 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、GC 的触发与对象分配

  1. 对象分配

    • 当对象被创建时,JVM 会根据对象的大小决定其分配的内存区域:

      • 大对象:如果对象的大小超过了 -XX:PretenureSizeThreshold 参数设置的值(默认是 0),该对象将直接分配到 老年代(Old Generation)。

      • 普通对象:若对象大小未超过阈值,则会分配到 年轻代(Young Generation)的 Eden 区

  2. Eden 区的分配

    • 对象默认会分配到 Eden 区,如果 Eden 区的空间不足,JVM 将会触发 Young GC

    • 在 Young GC 之前,会进行 空间分配担保,以确认如果 Eden 区空间不足时,Survivor 区是否能够容纳需要存活的对象。

二、Young GC 和空间分配担保

  1. Young GC:当 Eden 区满时,JVM 会触发 Young GC。Young GC 使用的是 标记-复制算法

    • 标记:通过 GC Roots 标记存活的对象。

    • 复制:将存活的对象从 Eden 区和 From Survivor 区复制到 To Survivor 区。

    • 清理:清除 Eden 区和 From Survivor 区的对象,释放空间。

  2. 空间分配担保:在 Young GC 之前,JVM 会检查是否有足够的空间在 Survivor 区容纳存活的对象。如果空间不足,就会触发一次 Full GC,即老年代的垃圾回收。

  3. 对象年龄判断:如果对象在多次 Young GC 后仍然存活,它的年龄会增加,达到一定年龄后会被晋升到 老年代

三、新生代的区分与存活

  • 新生代分为 一个 Eden 区两个 Survivor 区(From Survivor 和 To Survivor)。这是为了优化对象存活和避免内存浪费:

    • Eden 区:用来存放新创建的对象。

    • Survivor 区:用来存放经历过若干次 GC 后仍然存活的对象。

    • 如果只有一个 Eden 区和一个 Survivor 区,那么就无法很好地实现标记-复制算法,且会造成内存空间的浪费。

四、老年代垃圾回收(Full GC)

  1. Full GC 触发:当年轻代的对象无法容纳存活的对象时,会触发 Full GC,如果老年代的空间不足或者空间分配担保失败,可能会导致 OutOfMemoryError(OOM)。

  2. 老年代的 GC 算法

    • 现代的垃圾回收器通常使用 三色标记法,这种方法将回收过程分为以下四个阶段:

      • 初始标记:标记所有从 GC Roots 可达的对象。

      • 并发标记:在应用线程运行的同时,标记所有可能的对象。

      • 重新标记:对并发标记阶段未标记到的对象进行标记。

      • 并发清理:清理无用的对象。

    • 常见的老年代垃圾回收器有 CMS(Concurrent Mark-Sweep)和 G1(Garbage First)。

  3. Full GC 后空间不足:如果在进行 Full GC 后老年代空间依然不够,可能会触发 OOM,即 OutOfMemoryError

五、总结

  • 年轻代 GC(Young GC):基于标记-复制算法,涉及 Eden 区Survivor 区,并通过空间分配担保机制避免内存溢出。

  • 老年代 GC(Full GC):通过三色标记法进行清理,通常发生在年轻代的对象晋升到老年代后,老年代空间不足时会触发。

  • OOM(OutOfMemoryError):在 Full GC 后,如果空间依然不够,JVM 将抛出 OOM 错误。

公众号.png

1
JVM
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
    1. 支付宝打赏

      qrcode alipay
    2. 微信打赏

      qrcode weixin
博主关闭了所有页面的评论