g1收集器以region为基本单元重构内存管理,放弃固定代际边界,每个region动态承担eden、survivor、old或humongous角色;回收聚焦垃圾密度最高的region,辅以remembered set精准处理跨region引用,兼顾停顿控制与开销平衡。

G1 收集器的“化整为零”不是简单地把堆切小,而是用 Region 重构了内存管理的逻辑基础——它放弃传统连续代际边界,转而用大量独立、可复用、角色动态的小块区域(Region),让回收行为从“按代扫全堆”变成“按需挑最值钱的块来清”。
Region 是灵活的“多功能格子”,不是固定分区
每个 Region 大小在 1MB~32MB 之间(2 的幂次,如 2MB、4MB),总数最多 2048 个。它不预设属于年轻代还是老年代,运行时只承担一种逻辑角色:Eden、Survivor、Old 或 Humongous。比如一个 Region 当前是 Eden,对象晋升后可能立刻转为 Old;回收清空后又变为空闲 Region,下次分配时可重新指定角色。这种动态性打破了“代”在物理上的连续性和固化感。
回收只盯“垃圾密度”,不扫全堆
G1 不按代整体触发 GC,而是持续跟踪每个 Region 的垃圾占比(即“回收价值”)。它维护一个优先级列表,每次 GC(尤其是 Mixed GC)只选若干个垃圾最多、收益最高的 Old Region 加入回收集合。这样既避免了 CMS 或 Parallel Old 那样必须扫描整个老年代的开销,也绕开了 Full GC 的全局停顿风险。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- Young GC 仍回收所有 Eden + Survivor Region,但范围可控、停顿稳定
- Mixed GC 在 Young GC 基础上,额外加入一批高垃圾密度的老年 Region
- Humongous Region(≥ 单 Region 50% 大小的对象)被当作老年代一部分处理,超大对象占用连续多个 Humongous Region,GC 时一并回收
跨 Region 引用靠 Remembered Set 精准定位
局部变量在栈上,但它引用的堆对象可能跨 Region。G1 不扫描全部线程栈或全堆,而是在每个 Region 维护一个 Remembered Set(RSet),记录“哪些外部 Region 有指向本 Region 的引用”。这样在回收某个 Region 时,只需检查 RSet 中列出的少量跨区引用,彻底避开全堆遍历。
Region 划分让大堆更可控,但不等于无代价
Region 越小,堆能划分的 Region 数越多,RSet 占用内存和维护开销也越大;Region 过大,则回收粒度变粗,难以精准控停顿。JVM 默认按堆大小 ÷ 2048 向上取整到最近 2 的幂来设定 Region 大小(例如 4GB 堆 → 约 2MB/Region),这个平衡点兼顾了灵活性与元数据开销。实际调优中,-XX:G1HeapRegionSize 可手动干预,但需结合应用对象大小分布谨慎调整。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










