JVM 垃圾收集器ParNew&CMS与三色标记算法

一、垃圾收集算法

1. 分代收集理论

  • 核心思想:根据对象存活周期不同,将 Java 堆分为新生代和老年代,适配不同垃圾收集算法
  • 分代依据
    • 新生代:对象存活时间短,每次 GC 大量对象(近 99%)回收,适合复制算法
    • 老年代:对象存活概率高,无额外空间担保,适合标记 - 清除 / 标记 - 整理算法
  • 性能差异:标记 - 清除 / 标记 - 整理算法比复制算法慢 10 倍以上

2. 三大基础垃圾收集算法

(1)标记 - 复制算法
  • 原理:将内存分为大小相等的两块,每次使用一块;内存耗尽时,复制存活对象到另一块,清空原块
  • 适用场景:新生代(Serial、ParNew、Parallel Scavenge 收集器)
  • 优点:效率高,无内存碎片
  • 缺点:内存利用率低(仅 50%)
(2)标记 - 清除算法
  • 原理
    1. 标记阶段:标记存活对象(或需回收对象)
    2. 清除阶段:统一回收未标记(或已标记)对象
  • 适用场景:老年代(CMS 收集器)
  • 优点:实现简单
  • 缺点
    1. 效率低(标记对象过多时)
    2. 产生大量不连续内存碎片
(3)标记 - 整理算法
  • 原理:标记阶段与标记 - 清除一致,后续将所有存活对象向一端移动,清理边界外内存
  • 适用场景:老年代(Serial Old、Parallel Old 收集器)
  • 优点:无内存碎片,内存利用率高
  • 缺点:增加对象移动开销,效率低于复制算法

3. 算法对比总结

算法 优点 缺点 适用代际
标记 - 复制 效率高、无碎片 内存利用率低 新生代
标记 - 清除 实现简单、无需移动 效率低、产生碎片 老年代
标记 - 整理 无碎片、利用率高 效率低、有移动开销 老年代

二、垃圾收集器

1. 收集器分类与核心特性

(1)新生代收集器
收集器 线程模型 算法 核心特点 参数配置
Serial 单线程 标记 - 复制 简单高效、STW 时间长 -XX:+UseSerialGC
ParNew 多线程 标记 - 复制 可与 CMS 配合、多线程并发 -XX:+UseParNewGC
Parallel Scavenge 多线程 标记 - 复制 注重吞吐量、自适应调节 -XX:+UseParallelGC
(2)老年代收集器
收集器 线程模型 算法 核心特点 参数配置
Serial Old 单线程 标记 - 整理 单线程、作为 CMS 后备 -XX:+UseSerialOldGC
Parallel Old 多线程 标记 - 整理 注重吞吐量、Parallel 配套 -XX:+UseParallelOldGC
CMS 并发 标记 - 清除 低停顿、并发收集 -XX:+UseConcMarkSweepGC

2. 重点收集器详解

(1)Serial 收集器(串行收集器)
  • 线程模型:单线程(GC 线程 + STW 所有用户线程)
  • 算法实现:新生代复制算法,老年代标记 - 整理算法
  • 优点:无线程交互开销,单线程效率高
  • 缺点:STW 时间长,不适用于多核服务器
  • 适用场景:客户端应用、小型程序
(2)Parallel 系列收集器(吞吐量优先)
  • Parallel Scavenge(新生代)
    • 多线程收集,默认线程数 = CPU 核数(可通过 - XX:ParallelGCThreads 调整)
    • 核心目标:吞吐量(用户代码运行时间 / CPU 总时间)
    • 支持自适应调节(自动优化停顿时间 / 吞吐量)
  • Parallel Old(老年代)
    • 多线程 + 标记 - 整理算法
    • JDK8 默认老年代收集器
    • 适用场景:注重吞吐量、CPU 资源敏感的服务
(3)ParNew 收集器(CMS 配套)
  • 本质是 Parallel Scavenge 的多线程版本,唯一能与 CMS 配合的新生代收集器
  • 支持多线程并发收集,STW 时间比 Serial 短
  • 适用场景:Server 模式、需与 CMS 配合的服务
(4)CMS 收集器(低停顿优先)
  • 核心目标:最短回收停顿时间(用户体验优先)
  • 线程模型:并发收集(垃圾收集线程与用户线程同时运行)
  • 算法实现:标记 - 清除算法
  1. 初始标记:STW,记录 GC Roots 直接引用对象(速度快)
  2. 并发标记:无 STW,遍历对象图(耗时久,与用户线程并发)
  3. 重新标记:STW,修正并发标记的漏标(比初始标记久,远短于并发标记)
  4. 并发清理:无 STW,清理未标记对象(新对象标记为黑色)
  5. 并发重置:重置标记数据
  • 优点:并发收集、低停顿
  • 缺点
    1. CPU 资源敏感(与服务抢资源)
    2. 产生浮动垃圾(需下次 GC 清理)
    3. 内存碎片(可通过参数优化)
    4. 可能出现 Concurrent Mode Failure(触发 Serial Old 回收)
  • 核心参数
    • -XX:ConcGCThreads:并发 GC 线程数
    • -XX:+UseCMSCompactAtFullCollection:FullGC 后整理碎片
    • -XX:CMSInitiatingOccupancyFraction:老年代使用率阈值(默认 92%)
    • -XX:+CMSScavengeBeforeRemark:Remark 前触发 Minor GC

3. 收集器选择原则

  • 无万能收集器,需根据场景选择:
    • 客户端 / 小型应用:Serial + Serial Old
    • 吞吐量优先:Parallel Scavenge + Parallel Old
    • 低停顿 / 用户体验优先:ParNew + CMS
    • 大内存(>4G)+ 低停顿:G1/ZGC/Shenandoah(扩展)

三、底层核心机制

1. 三色标记算法(并发标记核心)

(1)核心概念
  • 标记规则 :按对象访问状态分为三种颜色:
    • 黑色:已访问,且所有引用已扫描(安全存活,不指向白色对象)
    • 灰色:已访问,但存在未扫描引用
    • 白色:未访问(分析结束后仍为白色则需回收)
  • 核心问题 :并发标记时,用户线程修改对象引用导致 "多标" 或 "漏标"
(2)问题解决方案
  • 多标(浮动垃圾)
    • 原因:并发标记中,GC Roots 销毁导致部分对象失去引用但已标记
    • 影响:不影响正确性,需下次 GC 清理
    • 处理:新对象直接标记为黑色(本轮不清理)
  • 漏标(严重 bug)
    • 原因:并发标记中,对象引用关系变化导致部分可达对象未标记
    • 解决方案:
      1. 增量更新(CMS 使用):黑色对象新增指向白色对象的引用时,记录引用并重新扫描
      2. 原始快照(SATB,G1/Shenandoah 使用):灰色对象删除指向白色对象的引用时,记录引用并重新扫描
(3)实现机制:读写屏障
  • 写屏障 :赋值操作前后插入处理逻辑(AOP 思想)

    • 增量更新:post_write_barrier记录新引用对象
    • SATB:pre_write_barrier记录旧引用对象
  • 读屏障:读取成员变量前插入处理逻辑(ZGC 使用),记录读取的对象

  • 代码模型

    // 写屏障示例
    void oop_field_store(oop* field, oop new_value) {
    pre_write_barrier(field); // SATB记录旧值
    *field = new_value;
    post_write_barrier(field, new_value); // 增量更新记录新值
    }

    // 读屏障示例
    oop oop_field_load(oop* field) {
    pre_load_barrier(field); // 记录读取对象
    return *field;
    }

2. 记忆集与卡表(跨代引用优化)

(1)核心问题
  • 新生代 GC 时,需扫描老年代中指向新生代的跨代引用(直接扫描老年代效率低)
(2)记忆集(Remember Set)
  • 数据结构:记录从非收集区到收集区的指针集合
  • 作用:避免扫描整个非收集区,仅需处理记忆集中的跨代引用
(3)卡表(Card Table)
  • 实现方式:字节数组CARD_TABLE[],每个元素对应 512 字节(2^9)的 "卡页"
  • 标记规则:卡页中存在跨代引用时,对应元素设为 1(变脏),否则为 0
  • 维护机制:通过写屏障触发卡表更新

四、JVM 参数优化实战(ParNew+CMS)

1. 亿级流量订单系统场景

  • 硬件配置:4 核 8G 服务器,JVM 分配 4G 内存
  • 业务特征:每秒产生 60MB 对象,大促峰值 300 单 / 秒
  • 核心目标:减少 Full GC 频率,控制 STW 时间

2. 优化后参数配置

复制代码
-Xms3072M -Xmx3072M  # 堆内存固定3G(避免动态扩容)
-Xmn2048M             # 新生代2G(占堆66.7%,减少Minor GC频率)
-Xss1M                # 线程栈大小
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M  # 元空间固定
-XX:SurvivorRatio=8   # Eden:S0:S1=8:1:1
-XX:MaxTenuringThreshold=5  # 对象5次Minor GC后进入老年代
-XX:PretenureSizeThreshold=1M  # 1M以上大对象直接进入老年代
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC  # 启用ParNew+CMS
-XX:CMSInitiatingOccupancyFraction=92  # 老年代使用率92%触发Full GC
-XX:+UseCMSCompactAtFullCollection  # Full GC后整理碎片
-XX:CMSFullGCsBeforeCompaction=3  # 3次Full GC后整理一次

3. 优化思路解析

  • 新生代扩容:减少 Minor GC 次数,避免对象频繁进入老年代
  • 调整对象晋升年龄:短期存活对象(几秒内)在 Minor GC 中回收
  • 大对象直接进入老年代:避免新生代复制开销
  • CMS 参数优化:平衡 Full GC 频率与碎片整理开销
相关推荐
百***07452 小时前
小米MiMo-V2-Flash深度解析:国产开源大模型标杆+一步API接入全指南
java·大数据·开源·php
信也科技布道师2 小时前
基石Redis实例自动化调度之路
java·开发语言·redis·自动化
zy_destiny2 小时前
SegEarth-OV系列(二):面向遥感图像的无训练开放词汇分割
人工智能·深度学习·算法·机器学习·计算机视觉·语义分割·开放词汇
m0_686041612 小时前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python
树码小子2 小时前
JVM初识 & JVM 内存区域划分
jvm
666HZ6662 小时前
程序设计竞赛java
java·开发语言
三不原则2 小时前
AIOps 技术架构全景:数据采集→分析→自动化执行全流程
java·架构·自动化
Coovally AI模型快速验证2 小时前
Meta ShapeR重磅开源:多模态3D生成,从真实杂乱视频中稳健重建
人工智能·学习·算法·yolo·3d·人机交互