G1和CMS垃圾回收器的区别
<p>一、核心设计目标</p><p>CMS:尽可能减少STW(Stop-The-World)时间,实现与用户线程的高并发。<br>
G1:兼顾低延迟和高吞吐量,在大内存场景下提供可预测的停顿时间。</p>
<p>二、<strong>内存管理模型</strong></p>
<p>CMS</p>
<ul>
<li><strong>分代设计</strong>:严格区分新生代(Eden、Survivor)和老年代,各自独立回收。</li>
<li><strong>内存碎片</strong>:采用 “标记 - 清除” 算法,可能产生大量内存碎片,导致 Full GC 频繁。</li>
</ul>
<p>G1</p>
<ul>
<li><strong>Region 分区</strong>:将堆划分为多个大小相等的Region(如 2MB / 个),每个 Region 动态扮演 Eden、Survivor 或 Old 区域。</li>
<li>跨代引用:通过 Remembered Set(RSet)记录跨 Region 引用,避免扫描整个堆。</li>
<li><strong>Humongous 区域</strong>:专门存储大对象(超过 Region 大小的 50%),减少内存碎片。</li>
</ul>
<p>三、GC 算法流程</p>
<p>CMS:</p>
<ul>
<li>初始标记(STW):标记 GC Roots 直接关联的对象。</li>
<li>并发标记:与用户线程并行,遍历所有可达对象。</li>
<li>重新标记(STW):修正并发期间用户线程修改的对象引用。</li>
<li>并发清除:与用户线程并行,清理未标记的对象。<br>
G1:</li>
<li>初始标记(STW):标记 GC Roots 直接关联的对象。</li>
<li>并发标记:与用户线程并行,遍历所有可达对象。</li>
<li>最终标记(STW):修正并发期间的引用变更。</li>
<li>筛选回收(STW):根据 Region 的垃圾占比,优先回收价值高的 Region(Garbage-First 策略)。</li>
</ul>
<p>四、STW 时间与性能</p>
<table>
<thead>
<tr>
<th>维度</th>
<th>CMS</th>
<th>G1</th>
</tr>
</thead>
<tbody>
<tr>
<td>STW 时间</td>
<td>并发标记和清除阶段不 STW,但最终标记可能较长(尤其是堆大时)。</td>
<td>筛选回收阶段可控制 STW 时间(通过-XX:MaxGCPauseMillis参数)。</td>
</tr>
<tr>
<td>内存碎片</td>
<td>标记 - 清除算法导致碎片化,可能触发 Full GC。</td>
<td>标记 - 整理算法(筛选回收阶段),减少碎片。</td>
</tr>
<tr>
<td>吞吐量</td>
<td>并发阶段不影响用户线程,但 GC 线程与用户线程竞争 CPU。</td>
<td>筛选回收时需 STW,但可通过调整 Region 数量优化。</td>
</tr>
</tbody>
</table>
<p>五、优缺点对比</p>
<p>CMS:</p>
<ul>
<li>优点:低延迟(尤其在堆较小时),适合响应时间敏感的应用。</li>
<li>缺点:
<ol>
<li>内存碎片严重,可能导致 Full GC 频繁。</li>
<li>并发阶段占用 CPU 资源,吞吐量下降。</li>
<li>无法处理浮动垃圾(并发期间新产生的垃圾)。</li>
</ol>
</li>
</ul>
<p>G1:</p>
<ul>
<li>优点:
<ol>
<li>可预测的停顿时间(通过 Region 策略)。</li>
<li>大内存下性能更优(如 4GB 以上)。</li>
<li>减少内存碎片(标记 - 整理算法)。</li>
</ol>
</li>
<li>缺点:<br>
2. 算法复杂度高,小内存场景下可能不如 CMS。<br>
3. 初始标记和筛选回收阶段仍需 STW。</li>
</ul>
<p>建议:</p>
<ul>
<li>新应用优先考虑 G1,尤其是大内存场景。</li>
<li>若应用对延迟极度敏感且堆较小(<4GB),可考虑 CMS,但需注意内存碎片问题。</li>
</ul><br><br>
来源:https://www.cnblogs.com/yinyixiao/p/18925854
頁:
[1]