JVM的垃圾处理机制详解

 更新时间:2025年09月28日 09:04:28   作者:三傻317  
JVM通过可达性分析确定垃圾对象,采用分代收集策略:新生代用复制算法(Eden+Survivor),老年代用标记-整理,现代收集器如G1兼顾吞吐与延迟,ZGC/Shenandoah实现超低延迟,适用于不同场景

JVM的垃圾处理机制

一、垃圾回收的流程

JVM 的垃圾回收(Garbage Collection, GC)大体分为两步:

  1. 可达性分析(找到谁是垃圾)
  2. 垃圾回收算法(使用合适的算法处理垃圾)

二、可达性分析

可达性分析用来判断一个对象是否还存活。

JVM 会从一些 GC Roots(如虚拟机栈中的局部变量、方法区的静态变量、本地方法栈中的引用等)开始向外搜索,如果能通过引用链找到某个对象,那么该对象就是“可达”的,不会被回收;反之,就是“垃圾”。

需要注意:对象被标记为垃圾后,并不会立刻清除,而是等到下一次触发 GC 时才会被统一清理。

三、垃圾回收算法

常见的 GC 基础算法有三种:

标记-清除(Mark-Sweep)

  • 过程:先标记所有存活对象,再清理未标记的垃圾对象。
  • 缺点:会产生 内存碎片

复制(Copying)

  • 过程:将存活对象复制到另一块内存区域,清空原区域。
  • 优点:速度快,没有碎片。
  • 缺点:理论上浪费一半空间。
  • 实际 JVM 中,新生代采用 Eden + 两个 Survivor 区(常见比例 8:1:1),大大提高了利用率。

标记-整理(Mark-Compact)

  • 过程:标记存活对象后,将它们移动到一边,保持内存连续,再清理边界之外的垃圾。
  • 优点:解决碎片问题。
  • 缺点:移动对象需要额外开销。

四、分代收集

不同算法各有优劣,JVM 采用 分代收集(Generational GC) 的思想:

新生代

  • 大多数对象朝生夕死。
  • 使用 复制算法,快速回收。
  • 新生代进一步划分为 1 个 Eden 区2 个 Survivor 区
  • 对象先分配在 Eden,经过多次 Minor GC 存活下来的对象晋升到老年代。

老年代

  • 存放生命周期较长的对象。
  • 使用 标记-整理算法(或标记-清除 + 整理)。
  • 避免来回复制带来的性能损耗。

大对象

  • 一些特别大的对象可能会直接分配到老年代,避免在新生代中频繁复制。

五、现代 GC 收集器

在实际 JVM 中,基础算法往往会被组合和优化,形成不同的收集器:

1. Serial GC

  • 特点:单线程,GC 时 Stop-The-World。
  • 算法:新生代用复制算法,老年代用标记-整理。
  • 适用场景:小应用、单核 CPU。

2. Parallel GC(吞吐量优先)

  • 特点:多线程并行回收,追求吞吐量最大化。
  • 适用场景:后台计算、大数据处理。
  • 缺点:GC 停顿仍然较长。

3. CMS(Concurrent Mark-Sweep)

  • 特点:并发标记和清除,减少停顿时间。
  • 算法:基于标记-清除。
  • 优点:适合对延迟敏感的应用(如 Web 服务)。
  • 缺点:会产生内存碎片,吞吐量低于 Parallel GC;在 JDK 9 起被标记为废弃。

4. G1(Garbage-First)

  • 特点:目前主流,JDK 9 之后默认收集器。
  • 设计:堆被划分为多个 Region,每次优先回收垃圾最多的 Region。
  • 优点:兼顾吞吐量和低延迟,可预测停顿时间(如 -XX:MaxGCPauseMillis=200)。
  • 算法:新生代 → 复制;老年代 → 标记-整理。

5. 其他新一代收集器

  • ZGC(JDK 11+):超低延迟,GC 停顿 < 10ms,支持 TB 级堆。
  • Shenandoah(JDK 12+):与 ZGC 类似,低延迟 GC。

总结

  • 新生代:复制算法(快速回收,大部分对象很快死亡)。
  • 老年代:标记-整理(减少碎片,适合长期对象)。

常见收集器

  • 小应用:Serial GC
  • 吞吐量优先:Parallel GC
  • 低延迟:CMS(逐渐淘汰)、G1(主流)
  • 超大堆/超低延迟:ZGC、Shenandoah

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • IDEA创建Servlet并配置web.xml的实现

    IDEA创建Servlet并配置web.xml的实现

    这篇文章主要介绍了IDEA创建Servlet并配置web.xml的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Spring Boot 整合RocketMq实现消息过滤功能

    Spring Boot 整合RocketMq实现消息过滤功能

    这篇文章主要介绍了Spring Boot 整合RocketMq实现消息过滤,本文讲解了RocketMQ实现消息过滤,针对不同的业务场景选择合适的方案即可,需要的朋友可以参考下
    2022-06-06
  • Java详解聊天窗口的创建流程

    Java详解聊天窗口的创建流程

    这篇文章主要介绍了怎么用Java来创建一个聊天窗口,聊天软件我们经常要用,但是你有想过自己怎么去实现它吗,感兴趣的朋友跟随文章往下看看吧
    2022-04-04
  • 使用Spring boot标记一个方法过时

    使用Spring boot标记一个方法过时

    这篇文章主要介绍了使用Spring boot标记一个方法过时,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Spring Boot部署到Tomcat过程中遇到的问题汇总

    Spring Boot部署到Tomcat过程中遇到的问题汇总

    这篇文章主要给大家分享了关于Spring Boot部署到Tomcat过程中遇到的一些问题,文中将解决的方法介绍非常详细,对同样遇到这个问题的朋友具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • JavaWeb之Filter过滤器详解

    JavaWeb之Filter过滤器详解

    本篇文章主要介绍了JavaWeb之Filter过滤器详解,实例分析了JavaWeb之Filter过滤器的使用技巧,非常具有实用价值,需要的朋友可以参考下。
    2017-03-03
  • RocketMQ实现随缘分BUG小功能示例详解

    RocketMQ实现随缘分BUG小功能示例详解

    这篇文章主要为大家介绍了RocketMQ实现随缘分BUG小功能示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Spring框架应用的权限控制系统详解

    Spring框架应用的权限控制系统详解

    在本篇文章里小编给大家整理的是关于基于Spring框架应用的权限控制系统的研究和实现,需要的朋友们可以学习下。
    2019-08-08
  • SpringKafka错误处理(重试机制与死信队列)

    SpringKafka错误处理(重试机制与死信队列)

    Spring Kafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04
  • Java中的NumberFormatException异常原因以及解决方案详解

    Java中的NumberFormatException异常原因以及解决方案详解

    这篇文章主要介绍了Java中的NumberFormatException异常原因以及解决方案详解,NumberFormatException 是 Java 中的一个异常类,通常在字符串转换为数字的过程中发生,它表示一个无效的数字格式,即字符串无法被正确解析为数字,需要的朋友可以参考下
    2024-02-02

最新评论