CMS(Concurrent Mark Sweep)垃圾回收器是Java虚拟机(JVM)中的一种垃圾回收算法,主要针对老年代的垃圾回收。CMS的目标是尽可能减少停顿时间,以提高应用程序的响应速度。以下是CMS垃圾回收机制的详细解释:
CMS 垃圾回收机制
1. 初始标记(Initial Mark)
- 阶段:STW(Stop The World)
- 操作:标记GC Roots能直接关联到的对象。
- 特点:这个阶段非常短暂,因为只需要标记少量对象。
2. 并发标记(Concurrent Mark)
- 阶段:并发
- 操作:从GC Roots开始遍历整个对象图,标记所有可达对象。
- 特点:与用户线程并发执行,不会导致STW。
3. 重新标记(Remark)
- 阶段:STW
- 操作:修正并发标记期间因用户程序继续运作而导致标记变化的部分对象。
- 特点:这个阶段比初始标记稍长,但仍然相对较短。
4. 并发清除(Concurrent Sweep)
- 阶段:并发
- 操作:清除标记阶段发现的垃圾对象。
- 特点:与用户线程并发执行,不会导致STW。
5. 重置(Reset)
- 阶段:并发
- 操作:重置CMS数据结构,为下一次垃圾回收做准备。
- 特点:与用户线程并发执行,不会导致STW。
CMS 的优缺点
优点
- 低停顿时间:通过并发标记和清除,减少了STW的时间,提高了应用程序的响应速度。
- 适合交互式应用:适用于对响应时间要求较高的应用,如Web服务器、在线交易系统等。
缺点
- 高内存消耗:需要更多的内存来保证并发回收的顺利进行,可能会导致“内存溢出”问题。
- 浮动垃圾:在并发标记和清除阶段,可能会有新的垃圾产生,这些垃圾无法在本次GC中被回收。
- 性能开销:并发标记和清除会占用一部分CPU资源,可能会影响应用程序的吞吐量。
配置参数
以下是一些常用的JVM参数,用于配置CMS垃圾回收器:
-XX:+UseConcMarkSweepGC # 使用CMS垃圾回收器
-XX:ParallelCMSThreads=4 # 设置CMS线程数
-XX:CMSInitiatingOccupancyFraction=70 # 设置老年代使用率达到70%时触发CMS GC
-XX:+UseCMSCompactAtFullCollection # 在Full GC后进行压缩,减少碎片
-XX:+UseCMSInitiatingOccupancyOnly # 只有在达到指定阈值时才触发CMS GC
示例代码
以下是一个简单的示例,展示如何在Java应用程序中启用CMS垃圾回收器:
public class CMSExample {
public static void main(String[] args) {
// 创建大量对象,模拟内存压力
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
byte[] bytes = new byte[1024 * 10]; // 10KB
list.add(bytes);
}
// 模拟长时间运行
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}