当前位置: 首页 > article >正文

GC垃圾回收机制-Serial GC

1. 概述

Serial GC 是 Java 虚拟机(JVM)中最基本和最简单的垃圾回收器。它采用单线程执行垃圾回收,并且在垃圾回收过程中会停止所有应用线程(即 Stop-the-World 事件)。虽然简单,但 Serial GC 在一些特定场景下仍然表现出色,尤其是在小型应用或单处理器环境下,它可以有效地减少复杂性和内存管理的开销。

2. Serial GC 简介

Serial GC 的特点是 单线程执行Stop-the-World。这意味着它只会使用一个线程来执行垃圾回收操作,不会并发处理垃圾回收任务。虽然这个特性在多线程应用或多处理器系统中可能导致性能瓶颈,但在一些小型或简单的系统中,Serial GC 的单线程执行和高效的内存管理方式仍然可以表现得很好。

JVM 默认不使用 Serial GC,但可以通过 JVM 启动参数启用它:

-XX:+UseSerialGC

该参数启用后,JVM 会使用 Serial GC 作为垃圾回收器来管理堆内存的回收。

3. Serial GC 的堆内存结构

Serial GC 使用的是经典的 分代垃圾回收 策略,将堆内存分为两个代:

  • 年轻代(Young Generation):存放新创建的对象,包括 Eden 区和两个 Survivor 区(S0、S1)。大部分对象会在年轻代分配,生命周期短的对象会在这里被回收。
  • 老年代(Old Generation):存放生命周期较长、经过多次垃圾回收仍然存活的对象。

当堆内存不足时,JVM 会触发垃圾回收,分别针对年轻代或老年代进行清理。Serial GC 的垃圾回收过程主要分为两部分:

  1. Minor GC:针对年轻代的垃圾回收。
  2. Major GCFull GC:针对老年代的垃圾回收,有时也会回收整个堆(包括年轻代和老年代)。

4. Serial GC 的工作原理

4.1 年轻代垃圾回收(Minor GC)

在年轻代的垃圾回收过程中,Serial GC 使用的是 标记-复制算法(Mark-Copy Algorithm)。这个算法的工作流程如下:

  1. 对象分配:大部分新对象会分配在年轻代的 Eden 区。当 Eden 区满时,会触发 Minor GC。

  2. 存活对象的标记:当触发 Minor GC 时,GC 首先标记 Eden 区和一个 Survivor 区中存活的对象(另一个 Survivor 区是空闲的)。

  3. 复制存活对象:存活的对象会从 Eden 区和使用的 Survivor 区复制到另一个空闲的 Survivor 区。如果对象已经存活了一定次数(年龄阈值),它们会晋升到老年代。

  4. 清空 Eden 和 Survivor 区:在复制存活对象后,GC 会清空 Eden 区和使用的 Survivor 区。

  5. 重新使用空闲 Survivor 区:Minor GC 完成后,空闲的 Survivor 区和 Eden 区可再次使用。

Minor GC 频繁发生,但由于年轻代通常较小,且大多数对象是短生命周期的,Minor GC 的执行速度非常快。

4.2 老年代垃圾回收(Major GC / Full GC)

老年代的垃圾回收是通过 标记-整理算法(Mark-Compact Algorithm)来完成的。该算法的步骤如下:

  1. 标记存活对象:首先,垃圾回收器会扫描整个老年代,并标记出其中仍然存活的对象。

  2. 整理存活对象:标记完成后,GC 会将存活的对象压缩到老年代的某一端,使得存活对象在内存中是连续的,减少内存碎片的产生。

  3. 释放无用对象:在整理完对象后,清理掉未标记的对象,并释放这些对象所占用的内存空间。

由于老年代存储的是生命周期较长的对象,Major GC 发生的频率较低,但每次发生时通常都会伴随较长的 Stop-the-World 停顿。

5. Stop-the-World 事件

每次执行 Minor GC 或 Major GC 时,Serial GC 都会触发 Stop-the-World 事件。也就是说,当垃圾回收发生时,所有应用线程都会被暂停,等待垃圾回收器完成其工作后,应用程序才能继续执行。

Stop-the-World 停顿是 Serial GC 最大的性能瓶颈,因为它会导致应用程序响应时间增加,尤其是当堆内存较大或垃圾回收工作量较大时,停顿时间会显著增加。

6. Serial GC 的使用场景

虽然 Serial GC 由于其单线程和 Stop-the-World 机制在大型应用中并不理想,但它在某些特定场景下依然具有优势:

  1. 单处理器环境:在单 CPU 核心的系统中,由于并发 GC 并没有明显的优势,Serial GC 的简单性反而可以带来较好的性能。

  2. 小型应用:对于一些堆内存较小且并发量低的应用,Serial GC 的单线程回收开销较小,且 Minor GC 的执行速度很快,因此它是一个不错的选择。

  3. 嵌入式系统:在资源有限的嵌入式设备上,Serial GC 因为其实现简单、资源开销小,适合作为垃圾回收器。

7. Serial GC 的优缺点

7.1 优点
  • 实现简单Serial GC 的实现相对简单,容易理解和调试。它只使用一个线程来进行垃圾回收,没有复杂的并行或并发机制,因此在某些场景下有很好的性能表现。

  • 适合小型应用:对于内存占用较小、并发量较低的应用,Serial GC 的性能相对较好,因为它避免了多线程之间的上下文切换开销。

  • 较小的内存开销Serial GC 不需要为垃圾回收器维护额外的线程和上下文,因此内存开销较低。

7.2 缺点
  • Stop-the-World 停顿Serial GC 在进行垃圾回收时,会暂停所有应用线程。对于大型应用或堆内存较大的应用,这种停顿可能会非常长,影响应用程序的响应时间和用户体验。

  • 单线程回收:在多核处理器上,Serial GC 无法充分利用多个 CPU 核心的优势,因此在并发量较高或需要高吞吐量的应用中,性能较差。

  • 不适合大内存应用Serial GC 在处理大堆内存时,Major GC 的执行时间较长,导致长时间的停顿,影响应用的可用性。

8. Serial GC 的调优参数

虽然 Serial GC 的调优选项相对较少,但仍有一些参数可以调整以优化其性能:

  1. -Xms 和 -Xmx:设置堆内存的初始大小和最大大小。

    • -Xms512m -Xmx1024m:将堆内存设置为 512MB 到 1024MB。
  2. -XX:NewRatio:设置年轻代与老年代的内存比例。较大的年轻代可以减少 Minor GC 的频率,但可能会增加 Major GC 的频率。

    • -XX:NewRatio=2:设置年轻代与老年代的比例为 1:2。
  3. -XX:SurvivorRatio:设置 Eden 区和 Survivor 区的比例。较大的 Eden 区可以容纳更多新对象,从而减少 Minor GC 的频率。

    • -XX:SurvivorRatio=8:设置 Eden 区与 Survivor 区的比例为 8:1。
  4. -XX:MaxTenuringThreshold:设置对象在年轻代中存活的次数阈值,超过该阈值的对象将晋升到老年代。

    • -XX:MaxTenuringThreshold=15:对象经过 15 次 Minor GC 后晋升到老年代。

9. Serial GC 与其他垃圾回收器

的对比

与其他垃圾回收器相比,Serial GC 的特点如下:

  • 与 Parallel GCParallel GC 也是基于 Stop-the-World 事件的垃圾回收器,但它使用多个线程并行执行垃圾回收任务,适合多处理器环境。相比之下,Serial GC 只使用单线程,因此在多核环境下效率较低。

  • 与 CMS GCCMS GC 是一种并发垃圾回收器,它尝试与应用线程并行工作,以减少 Stop-the-World 停顿时间。CMS 更适合低延迟的应用,而 Serial GC 在这种场景下表现较差。

  • 与 G1 GCG1 GC 是面向大内存应用的垃圾回收器,旨在提供可预测的低停顿时间。相比之下,Serial GC 在处理大堆内存时停顿时间较长,无法提供相同级别的性能。

10. 总结

Serial GC 是 Java 虚拟机中的一种简单、单线程的垃圾回收器,适用于小型应用、单处理器系统或嵌入式设备。虽然它的实现简单,适合低并发环境,但由于其 Stop-the-World 特性和单线程回收的限制,它不适合大内存或高并发的应用。

在选择 Serial GC 之前,需要根据应用程序的特点和需求进行权衡。如果应用规模较大或需要更低的延迟,可以考虑使用 Parallel GCCMS GCG1 GC 等更加复杂和高效的垃圾回收器。


http://www.kler.cn/a/309125.html

相关文章:

  • C语言第九周课——经典算法
  • 问:MySQL主从同步的机制梳理?
  • 【时间之外】IT人求职和创业应知【34】-人和机器人,机器人更可靠
  • mapreduce 将数据清洗后保存到 hbase
  • 从0开始学docker (每日更新 24-11-7)
  • 数据分析那些事儿——时间片轮转实验
  • Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
  • Linux下root用户共享conda环境给其他用户
  • 力扣121-买卖股票的最佳时机(Java详细题解)
  • Encountered 31 files that should have been pointers, but weren‘t:(已解决,无废话)
  • System.out源码解读——err 和 out 一起用导致的顺序异常Bug
  • 论文翻译:USENIX-2021 Extracting Training Data from Large Language Models
  • 网络设备登录——《路由与交换技术》实验报告
  • 养宠浮毛严重怎么清理?希喂、范罗士、IAM宠物空气净化器真实测评
  • C++:初始化列表
  • 在线包装盒型生成工具,各种异型包装盒型,PDF导出方便
  • 【蜡笔小新专享】安装虚拟机、PHP、DVWA
  • Linux容器化管理——Docker常见命令总结
  • Apache Pulsar 与 Kafka Streams
  • React实现类似Vue的路由监听Hook
  • 在新电脑上将文件推送到已有的 Git 仓库
  • 【编程基础知识】Java命名规范及最佳实践
  • 孙怡带你深度学习(2)--PyTorch框架认识
  • Unity实战案例全解析:PVZ 植物卡片状态分析
  • 【乐企】基础版接口代码实现
  • Spring Boot校园管理系统:技术选型与架构设计