G1的内存划分
G1 是 JDK 7u4 引入的服务器级垃圾收集器,其内存划分与传统分代收集器有本质不同。以下是 G1 内存结构的完整解析:
内存分区结构
graph TD
A[G1 堆内存] --> B[等大Region]
A --> C[大对象Region]
B --> B1[默认大小: 1MB-32MB]
B --> B2[可调参数: -XX:G1HeapRegionSize]
C --> C1[最小单位: 1个Region]
C --> C2[可扩展: 多Region连续存储]
C --> C3[触发条件: >50% RegionSize]
style B2 white-space:normal
graph TD
A[G1 内存结构] --> B[逻辑分代]
A --> C[物理分区]
B --> B1[年轻代 Young Generation]
B --> B2[老年代 Old Generation]
B --> B3[大对象区 Humongous]
C --> C1[固定大小Region]
C1 --> D[Eden Regions]
C1 --> E[Survivor Regions]
C1 --> F[Old Regions]
C1 --> G[Humongous Regions]
C1 --> H[空闲Region]
一、G1 的分代模型(逻辑分代)
1. 与传统分代收集器的对比
| 特性 | 传统分代收集器 | G1 收集器 | 核心差异 |
|---|---|---|---|
| 内存隔离 | 严格物理隔离年轻代与老年代有固定边界 | 逻辑分代无物理隔离 | G1 取消物理隔离,实现动态区域分配 |
| 内存布局 | 连续内存块各代占据连续地址空间 | 分区模型堆划分为等大小 Region | G1 的 Region 分区避免内存碎片 |
| 比例控制 | 固定比例通过 -Xmn/-XX:NewRatio 等参数静态设置 | 动态调整运行时根据 GC 效率自动调节各代占比 | G1 实现运行时自适应优化 |
| 大对象处理 | 存储在老年代可能导致内存碎片 | 专用 Humongous Region全局列表管理 | G1 隔离大对象避免影响常规对象 |
| 回收单位 | 整个分代Young GC 处理整个年轻代 | 单个 Region可选择高收益 Region 优先回收 | G1 实现更精准的回收控制 |
2. 逻辑分代的实现
G1的内存都是Region,所以新生代和老年代只是分布在不同的Region
graph LR
年轻代 --> 区域[Eden/Survivor Region]
老年代 --> 区域[Old Region]
大对象 --> 区域[Region]
G1控制器 --> 监控[监控GC效率]
监控 --> 调整[动态调整区域分配]
二、Region 分区设计(物理实现)
1. Region 的核心特性
classDiagram
class Region {
+大小:1MB~32MB(默认堆大小/2048)
+类型:Eden/Survivor/Old/Humongous
+标记:存活对象信息
+RSet:记录引用关系
}
2. 等大 Region(固定大小分区)
| 特性 | 说明 |
|---|---|
| 默认大小 | 1MB-32MB,根据堆大小自动计算 |
| 计算公式 | RegionSize = HeapSize ÷ 2048 |
| 大小约束 | 1MB ≤ RegionSize ≤ 32MB |
| 内存对齐 | 始终为 2 的幂 (1, 2, 4, 8, 16, 32MB) |
3. Region 类型与功能
| Region 类型 | 存储对象 | 回收策略 |
|---|---|---|
| Eden Region | 新创建的小对象 | 只被 Young GC 回收 |
| Survivor Region | 年轻代存活对象 | Young GC 后晋升 |
| Old Region | 老年代对象 | Mixed GC 回收 |
| Humongous Region | 大对象(>50% RegionSize) | 直接老年代回收 |
| 空闲 Region | 未分配 | 可转为任意类型 |
三、对象存储策略
1. 小对象分配(≤50% RegionSize)
sequenceDiagram
应用线程 ->> TLAB: 线程本地分配缓冲区
TLAB ->> Eden Region: 分配小对象
alt TLAB空间不足
Eden Region-->>新Region: 申请新Region
新Region-->>TLAB: 提供新空间
end
2. 大对象分配(>50% RegionSize)
flowchart TD
大对象请求 --> 判断{是否>单个Region?}
判断 -->|是| 连续分配[分配连续Region]
判断 -->|否| 单Region[分配单个Region]
连续分配 --> 标记[起始Region标记H-start]
连续分配 --> 后续[后续Region标记H-cont]
全局记录 --> 列表[加入全局大对象列表]
四、内存管理关键机制
1. 动态区域调整
gantt
title G1 区域动态调整示例
dateFormat GC
axisFormat %s
section 初始状态
Eden : des1, 0, 40
Survivor : des2, 0, 10
Old : des3, 0, 50
section Young GC后
Eden重置 : 40, 30
Survivor晋升 : 45, 5
Old增加 : 50, 5
section Mixed GC后
Old回收 : 55, -15
2. 巨型对象特殊处理
# 大对象阈值(默认50% RegionSize)
-XX:G1HeapWastePercent=10 # 允许浪费空间比例
-XX:G1MixedGCLiveThresholdPercent=65 # 混合GC存活对象阈值
五、技术总结
G1 内存设计的三大突破:
mindmap
root((G1内存设计优势))
分区模型
固定大小Region
消除内存碎片
并行回收基础
逻辑分代
保持分代优势
动态调整比例
优化回收策略
巨型对象处理
专用Humongous区
全局列表管理
特殊回收策略
关键结论:
- G1 采用 逻辑分代+物理分区 的创新模型:
- 逻辑分代:保留年轻代(Young)、老年代(Old)、大对象(Humongous)概念
- 物理分区:堆划分为固定大小(1-32MB)的 Region
- 对象存储策略:
- 小对象(≤50% Region):存储在 Eden Region
- 普通对象:晋升到 Old Region
- 大对象(>50% Region):直接分配到 Humongous Region
- 动态调节:运行时根据GC效率动态调整各代Region比例,避免了分代之间空间分配不合理的问题。