cms收集器(concurrent mark sweep)的主要缺点包括:在并发标记阶段会占用部分系统资源,导致应用线程吞吐量降低;存在浮动垃圾问题,即并发清理期间产生的新垃圾无法回收,需等待下一次gc周期;由于采用标记-清除算法,容易产生内存碎片,导致大对象分配失败并触发full gc;以及cms提供的是低停顿时间的服务,而非最低停顿时间。

为什么CMS会产生内存碎片
CMS产生内存碎片的根本原因在于其使用的“标记-清除”(Mark-Sweep)算法。该算法在回收内存时,只标记需要回收的对象并清除它们,但不会整理剩余存活对象的内存空间。这导致释放出的内存块是分散的、不连续的。当应用程序尝试分配一个比任何单个空闲内存块都大的对象时,即使总空闲内存足够,也会因为找不到连续的空间而触发Full GC。这种碎片化现象在长期运行且对象生命周期差异较大的应用中尤为明显。

import java.util.ArrayList;
import java.util.List;
public class CMSFragmentationDemo {
public static void main(String[] args) {
// 模拟CMS收集器的内存碎片过程
List<byte> list = new ArrayList();
// 1. 分配大量小对象,填满老年代
for (int i = 0; i <h2>什么是浮动垃圾及其影响</h2>
<p>浮动垃圾(Floating Garbage)是指CMS收集器在并发清理阶段(Concurrent Cleanup)结束后,到下一次GC开始之前这段时间内,由用户线程新创建的垃圾对象。由于CMS的设计目标是尽量减少STW(Stop-The-World)时间,它无法在并发阶段实时处理所有新产生的垃圾。这些“浮动”的垃圾必须留待下一次GC周期才能被回收。这意味着CMS收集器的实际可用内存会比理论值少,通常需要通过调整`-XX:CMSInitiatingOccupancyFraction`参数来提前触发GC,以避免因内存不足而导致的并发模式失败(Concurrent Mode Failure)。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill12835" title="JavaScript 测试模式"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20cf0281539.jpg" alt="JavaScript 测试模式" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill12835" title="JavaScript 测试模式" class="overflowclass">JavaScript 测试模式</a>
<p class="overflowclass">使用 Jest、Vitest 和 Testing Library 实施全面的测试策略,包括单元测试、集成测试和端到端测试,涵盖模拟、测试夹具和测试驱动开发。在编</p>
</div>
<a rel="nofollow" href="/xiazai/skill12835" title="JavaScript 测试模式" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p><img src="https://img.php.cn/upload/article/001/242/473/179471836994706.png?x-oss-process=image/resize,p_40" alt="Java 垃圾回收 中 CMS收集器有什么缺点"></p>
<pre class="brush:php;toolbar:false;">import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
public class FloatingGarbageDemo {
public static void main(String[] args) {
// 获取CMS收集器的统计信息
List<garbagecollectormxbean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean bean : gcBeans) {
if (bean.getName().contains("CMS")) {
System.out.println("GC Name: " + bean.getName());
System.out.println("Collection Count: " + bean.getCollectionCount());
System.out.println("Collection Time: " + bean.getCollectionTime() + "ms");
}
}
// 模拟高负载下的浮动垃圾产生
int count = 0;
while (true) {
// 快速创建和丢弃对象
Object obj = new Object();
obj = null; // 变为垃圾
count++;
if (count % 1000000 == 0) {
System.out.println("Created and discarded " + count + " objects.");
}
}
}
}</garbagecollectormxbean>
CMS并发模式失败的原因是什么
CMS并发模式失败(Concurrent Mode Failure)发生在CMS并发清理阶段,当老年代剩余空间不足以容纳新晋升的对象或新分配的大对象时。这种情况通常由两个原因引起:一是浮动垃圾过多,导致老年代实际可用空间不足;二是内存碎片化严重,虽然总空闲内存足够,但没有足够的连续空间。一旦发生并发模式失败,JVM会回退到Serial Old收集器进行串行标记-清除,这将导致长时间的STW停顿,完全违背了CMS设计初衷。为了避免这种情况,通常需要设置`-XX:+UseCMSCompactAtFullCollection`在Full GC时进行内存整理,或者调低CMS的触发阈值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










