---
### **1. 核心概念**
• **Remembered Set(记忆集)**:
一个**抽象概念**,指垃圾收集器(GC)中用于**记录跨区域(或跨代)引用**的数据结构。例如,在分代GC中,记忆集记录老年代对象对年轻代的引用,避免全堆扫描。
• **Card Table(卡表)**:
记忆集的**一种具体实现方式**,通常通过**位图(bitmap)** 标记内存块(卡页)是否包含跨区域引用。卡表是记忆集在技术实现上的具体表现。
---
### **2. 两者的关系**
• **记忆集是接口,卡表是实现**:
• **记忆集**定义功能:记录外部区域到本区域的引用。
• **卡表**是其中一种实现方式,其他实现可能包括哈希表、指针数组等。
• **所有卡表都是记忆集,但记忆集不一定是卡表**:
例如,ZGC可能使用其他数据结构(如指针数组)实现记忆集,而G1默认使用卡表。
---
### **3. 卡表的工作原理**
1. **内存分块**:
堆内存被划分为固定大小的**卡页(Card Page)**,如512字节或1KB。
```plaintext
| Card 0 | Card 1 | Card 2 | ... | Card N |
```
2. **标记引用变更**:
• 当应用线程修改对象引用时(如老年代对象A引用年轻代对象B),**写屏障(Write Barrier)** 会标记对应的卡页为“脏”(Dirty)。
• 例如,对象A所在的卡页被标记为脏页。
3. **GC阶段扫描**:
• 在年轻代GC时,只需扫描**脏卡页**中的对象,快速找到跨代引用,避免扫描整个老年代。
---
### **4. 卡表的优缺点**
• **优点**:
• **空间效率高**:用位图标记卡页,占用内存小。
• **更新快速**:写屏障仅需设置位图位,开销低。
• **缺点**:
• **精度不足**:一个卡页被标记为脏,需扫描整个卡页内所有对象(即使只有1个引用)。
• **维护开销**:频繁修改引用时,写屏障可能影响吞吐量。
---
### **5. 示例场景**
• **分代GC(如ParNew+CMS)**:
• 老年代对象A引用年轻代对象B。
• 卡表标记A所在的卡页为脏。
• 年轻代GC时,仅扫描脏卡页,发现A→B的引用,将B晋升到老年代。
• **G1的Region化堆**:
• 每个Region对应一个记忆集(卡表实现)。
• Region Y的记忆集记录所有指向Y的外部引用所在的卡页。
---
### **6. 其他记忆集实现**
• **指针数组**:
直接存储跨区域引用的指针列表(如ZGC的部分实现)。
• **优点**:精确到单个引用。
• **缺点**:空间占用大,更新成本高。
• **哈希表**:
按对象地址哈希存储跨区域引用。
• 适用于稀疏引用场景,但查询复杂度较高。
---
### **7. 总结**
• **记忆集(Remembered Set)**:
广义的跨区域引用记录机制,是垃圾收集器的核心数据结构。
• **卡表(Card Table)**:
记忆集的一种高效实现方式,通过位图标记内存块,平衡精度与性能。
• **关键区别**:
• 记忆集是逻辑概念,卡表是物理实现。
• 卡表牺牲部分精度换取空间和时间效率,而其他实现可能更精确但成本更高。
**实际应用**:
• G1、CMS等收集器默认使用卡表实现记忆集。
• 在需要高精度时(如实时系统),可结合其他数据结构优化。
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传