第1章 垃圾回收概述

依据彭成寒《JVM G1源码分析和调优》完整目录独立重构:建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言

第1章 垃圾回收概述

本页对应原书正式结构中的 第1章 垃圾回收概述。课程不复制原文,而是按目录节点独立还原算法、jdk8u60 HotSpot源码路径、日志语义和调优证据。当前任务是:建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言。

可验收学习目标

学习目标

  • 能解释本页14个正式节点在G1对象图、线程、Region与回收周期中的责任。
  • 能实现一个固定源码提交、JDK、堆、参数、工作量和停止条件的可重复GC实验。
  • 能比较源码分支、统一时间线日志、对象状态与性能指标,区分相关性和因果。
  • 能设计失败反例、资源隔离、参数回滚与版本迁移记录,让他人独立重放。

本页交付 算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。首要陷阱是“把并行与并发混同,只按算法名称判断停顿和吞吐,或跳过对象图与工作负载直接比较收集器”。所有参数实验必须先预测收益和负面影响,再运行。

官方目录逐节点复刻

第1章 垃圾回收概述

正式节点 1/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“第1章 垃圾回收概述”。

1.1 Java发展概述

正式节点 2/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.1 Java发展概述”。

1.2 本书常见术语

正式节点 3/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.2 本书常见术语”。

1.3 回收算法概述

正式节点 4/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3 回收算法概述”。

1.3.1 分代管理算法

正式节点 5/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3.1 分代管理算法”。

1.3.2 复制算法

正式节点 6/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3.2 复制算法”。

1.3.3 标记清除

正式节点 7/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3.3 标记清除”。

1.3.4 标记压缩

正式节点 8/14。 区分疏散失败、串行与并行Full GC,逐步验证标记、地址计算、引用更新、对象移动和后处理,并标明JDK版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3.4 标记压缩”。

1.3.5 算法小结

正式节点 9/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.3.5 算法小结”。

1.4 JVM垃圾回收器概述

正式节点 10/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.4 JVM垃圾回收器概述”。

1.4.1 串行回收

正式节点 11/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.4.1 串行回收”。

1.4.2 并行回收

正式节点 12/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.4.2 并行回收”。

1.4.3 并发标记回收

正式节点 13/14。 用三色对象图和SATB不变量解释并发修改,沿初始标记、根扫描、并发、再标记、清理与Mixed启动保全证据。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.4.3 并发标记回收”。

1.4.4 垃圾优先回收

正式节点 14/14。 把术语放回对象图、线程和时间线,说明输入、状态变化、日志证据与调优副作用;源码和日志必须来自同一版本。节点结论服务于“建立分代、复制、标记清除、标记压缩及串行、并行、并发、垃圾优先四类回收的共同语言”,并写入算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例。

先预测一个能排除当前解释的结果,再运行基线与单变量对照。验收注明源码提交、JDK、参数、堆、工作量、采集窗口和单位;若只有流程背诵或工具截图,就没有覆盖“1.4.4 垃圾优先回收”。

从Region和时间线开始

G1把堆划分为大小相等的Region,但Region不是固定代;Eden、Survivor、Old、Humongous与空闲状态会随分配和回收改变。决定本轮扫描和复制边界,避免每次扫描整个堆。任何流程图都要同时标出对象来源、目标Region、引用更新和失败余量。

写入引用时,G1通过写屏障把脏卡放入队列,后台Refine线程更新RSet;当队列积压跨过区间,应用线程也可能承担处理。连接应用写入与后续扫描。调优Refine不能只看后台线程CPU,还要观察Mutator协助、队列水位、跨Region引用率和暂停中的RSet扫描成本。

G1的停顿目标是预测输入,不是硬实时保证。影响年轻代长度和CSet选择,但实际时间还取决于存活率、RSet、复制带宽、工作线程平衡与安全点。缩短目标可能增加GC频率和CPU,放宽目标可能扩大年轻代和单次复制;所以收益必须在完整工作量中衡量。

并发标记遵守SATB视图,允许应用线程继续修改对象图,并通过屏障保留必要引用。不意味着没有浮动垃圾,也不负责移动对象。初始标记、根区扫描、并发标记、再标记和清理必须与之后的Mixed回收区分;Mixed才会在暂停中疏散选中的Old Region。

对象复制需要目标空间。存活估计错误、Humongous碎片、并发周期过晚或分配突增可能导致,进一步走向Full GC。修复不能只加堆;还要确认并发标记启动、存活集、Region余量、分配速率、引用处理和安全点。Full GC后的暂时恢复只说明状态被压缩,不证明根因消失。

源码、日志与版本证据

原书源码基线jdk8u60的G1目录和后续OpenJDK不同。每条源码结论记录仓库、提交、文件、函数、调用者和关键条件;书中为讲解而删节的大括号、统计和辅助路径不能当作可编译原文。对JDK 10并行Full GC,必须切换到对应仓库重新建立调用链,禁止把两个版本片段拼成一个虚构实现。

日志按统一时钟构建阶段树:暂停开始与结束、到达安全点、根扫描、RSet更新、对象复制、引用处理、清理和并发阶段。总停顿等于多个阶段和同步成本,阶段并行也可能因负载不均产生长尾。先保存原始日志,再解析;解析器必须匹配JDK格式,未知字段不能静默丢弃。

参数分产品、诊断、实验和开发类别,适用性取决于构建与版本。参数存在不表示应修改。每次只改变一项,记录默认值来源、预测机制、成功指标、负面指标和回滚阈值。若日志改善但吞吐、CPU、RSS、错误率或恢复时间恶化,不能称为调优成功。

安全点是独立诊断维度。应用停止前等待线程到达安全点的时间不等于GC阶段执行时间;长本地调用、缺少轮询或线程状态都可能拉长Time to Safepoint。采集时把TTSP和安全点内工作拆开,否则增加GC并行线程无法解决进入安全点之前的延迟。

引用处理、字符串去重和NMT同样有边界。软弱虚引用的处理受可达性与策略影响,字符串去重收益依赖内容分布,NMT不等于进程RSS。所有平均收益必须回到本应用的对象直方图、分配率、CPU和长期保留验证,不能照搬书中或文档的示例百分比。

最小可执行切片

先固定案例与环境:

record G1Case(String sourceCommit, String javaVersion, String flags,
              String workloadHash, long heapBytes, String logHash) {}
var baseline = captureBeforeRun();

分析器保留阶段树,不只抓总暂停:

var event = parseGcEvent(rawLog, exactJdkVersion);
assertTrue(event.hasSafepointBoundary());
assertEquals(event.pauseNanos(), event.phaseTree().criticalPathNanos());

交接合同要求单变量和回滚:

Feature: 第1章 垃圾回收概述
  Scenario: validate a G1 source and tuning hypothesis
    Given jdk8u60 or the explicitly selected source tree and a fixed workload
    When 对同一对象图手工执行复制、标记清除与标记压缩,比较空间、移动、暂停和并发读写约束
    Then source branches, raw logs, object states, and metrics agree
    And adverse effects, version limits, and rollback thresholds are recorded

定量判断

Region数量与堆和Region大小相关,大对象需要连续Region,实际边界还包含对齐:

N_{regions}approx rac{HeapSize}{RegionSize},qquad N_{humongous}=leftlceil rac{AlignedObjectSize}{RegionSize} ight ceil

停顿关键路径应按阶段和并行失衡解释:

Tpause=Tttsp+Troots+Trset+Tcopy+Tref+Tcleanup+TsyncT_{pause}=T_{ttsp}+T_{roots}+T_{rset}+T_{copy}+T_{ref}+T_{cleanup}+T_{sync}

调优同时约束吞吐、暂停和资源:

Throughput= rac{Work}{T_{wall}},qquad GCOverhead= rac{T_{gc}}{T_{wall}},qquad L_{p99}leq Budget

并发标记必须赶在空间耗尽前完成,可用预算模型表达风险而非给出万能IHOP:

T_{mark}+T_{margin}< rac{FreeBytes-ReserveBytes}{AllocationRate}

这些公式是调查框架,不替代G1内部预测。数字必须注明单位、重复次数、分位数、CPU、NUMA、容器限制、预热和存活率。

本章回顾

本页从第1章 垃圾回收概述覆盖到1.4.4 垃圾优先回收,共14个正式节点。最小闭环是建立Region和引用图,以同一源码与日志重放“对同一对象图手工执行复制、标记清除与标记压缩,比较空间、移动、暂停和并发读写约束”,再用算法对象移动图、回收器时间线、停顿与吞吐权衡表、术语反例证明机制、参数收益、副作用、版本与回滚。若仍落入“把并行与并发混同,只按算法名称判断停顿和吞吐,或跳过对象图与工作负载直接比较收集器”,应回到节点补做状态和失败对照。

练习

问题 1:如何为第1章 垃圾回收概述建立源码到日志的最小证据链?

问题 2:为什么“把并行与并发混同,只按算法名称判断停顿和吞吐,或跳过对象图与工作负载直接比较收集器”会破坏调优结论?

问题 3:迁移到现代JDK时应怎样处理原书jdk8u60结论?

名词解释

本章出现的专业名词,用大白话再讲一遍。

Collection Set
一次暂停中计划回收的一组Region。
Remembered Set
记录其他Region中指向本Region引用位置的反向索引。
Dirty Card Queue
记录待精炼脏卡地址的线程本地或全局队列。
停顿预测模型
使用近期阶段耗时及偏差估计给定停顿预算能容纳多少回收工作的模型。
Snapshot At The Beginning
并发标记开始时逻辑对象图的快照语义,通过写屏障避免漏标。
Evacuation Failure
暂停疏散时目标空间不足,部分对象无法按计划复制的失败状态。

← 上一页:《JVM G1源码分析和调优》权威学习地图 · 下一页:第2章 G1的基本概念 →

资料与写作方式声明

本章以彭成寒《JVM G1源码分析和调优》权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…