CMS概述
并发标记清理垃圾回收(Concurrent Mark and Sweep GC)算法的主要目标是在GC过程中,减少暂停用户线程的次数以及在不得不暂停用户线程的请夸功能,尽可能短的暂停用户线程的时间。这对于交互式应用,比如web应用来说,是非常重要的。
CMS垃圾回收针对新生代和老年代采用不同的策略。相比同吞吐量垃圾回收,它要复杂的多。吞吐量垃圾回收在执行时必须暂停用户线程,并且暂停的时间可能比较长,吞吐量垃圾回收在运行时,完全无视了应用线程。不过这么做也有个好处,就是确保了GC线程在运行时不会跟用户线程发生线程互斥等线程同步问题,保证了用户数据。
但是,CMS垃圾回收的目标是要尽可能少的暂停用户线程,不得不暂停时,暂停用户线程的时间也要尽可能的短暂,它采用GC线程和用户线程同时工作的方式来保证用户系统的活跃性。凡事有利必有弊,这种方式的弊端在于可能潜在的引入GC和用户线程同步问题、数据一致性问题。
为了解决GC线程和用户线程的安全正确的同时并发,CMS垃圾回收包含如下几个GC回收阶段。
CMS垃圾回收的阶段
一次完整的CMS垃圾回收分为6个阶段。其中四个阶段是GC线程跟用户线程并发执行的,有两个阶段是JVM暂停用户线程,仅仅GC线程运行的。
- Initial Mark: The application threads are paused in order to collect their object references. When this is finished, the application threads are started again.
- Concurrent Mark: Starting from the object references collected in phase 1, all other referenced objects are traversed.
- Concurrent Preclean: Changes to object references made by the application threads while phase 2 was running are used to update the results from phase 2.
- Remark: As phase 3 is concurrent as well, further changes to object references may have happened. Therefore, the application threads are stopped once more to take any such updates into account and ensure a correct view of referenced objects before the actual cleaning takes place. This step is essential because it must be avoided to collect any objects that are still referenced.
- Concurrent Sweep: All objects that are not referenced anymore get removed from the heap.
- Concurrent Reset: The collector does some housekeeping work so that there is a clean state when the next GC cycle starts.
因此,CMS GC并非不暂停用户线程,只是暂停的时间比较短。上面的步骤是发生在老年代堆的垃圾回收,对于新生代,新生代仍然采用完全暂停用户线程的做法,这是因为新生代的垃圾回收通常非常快,都是朝生夕死的对象
CMS垃圾回收的问题
CMS垃圾回收有两个问题:
a.堆的碎片问题
b.频繁对象空间分配
1. 堆的碎片问题
不同于吞吐量垃圾回收,CMS垃圾回收没有提供内存碎片的整理功能,因此,极坏的情况下老年代堆空间有可能出现大量的内存空间碎片,即使老年代堆空间足够大,也有可能因为找不到连续的内存空间而导致内存分配失败而引起全量GC,全量GC(Full GC)采用的算法跟吞吐量GC一样,能够解决碎片问题,但是会暂停用户线程。
2.频繁对象空间分配
这里的频繁对象空间分配是指创建对象的操作远远超过删除对象的操作(比如,往一个集合中放30万个对象),这时,如果达到新生代堆容量上限,会将位于新生代的还在集合中的对象
移动到老年代,如果老年代有较多碎片,频繁的将对象从新生代移动到老年代,也会触发Full GC,
解决上面两个问题的做法是,如果使用CMS垃圾回收,那么需要将新生代的空间分配大一点,避免出现新生代对象向老年代移动的情况。
与CMS相关的JVM参数
1.-XX:+UseConcMarkSweepGC
指示JVM使用CMS GC,而不是默认的ThroughOutput GC
2.-XX:+UseParNewGC
当使用CMS GC时,这个参数指示JVM对新生代堆空间采用多线程并行的方式进行GC。这个参数乍看上去有点多余,因为Throughput GC已经有一个称为-XX:+UseParallelGC的JVM
参数,并且CMS对于新生代的垃圾回收方式与Througput GC的做法一样。那为什么对于CMS垃圾回收,CMS专门定义-XX:UseParNewGC
这个参数呢?因为对于CMS垃圾回收,对于新生代和老年代的垃圾回收,采用了两种不同的算法,因此对于新生代使用-XX:UseParNewGC
,而对于老年代则沿用Throughput GC一样的参数-XX:+UseParallelGC。
需要注意的是,-XX:+UseConcMarkSweepGC启用后,
-XX:UseParNewGC将默认启用,因此如果不想使用
-XX:UseParNewGC这个参数,则需要使用
-XX:-UseParNewGC
3.-XX:+CMSConcurrentMTEnabled
使用这个参数指示JVM,在CMS垃圾回收的并发阶段(不是暂停用户线程的阶段),使用多个GC多线程参与GC,这些GC线程与用户线程并发执行,这个参数默认是开启的
4.-XX:ConcGCThreads
这个参数用来设置执行CMS并发收集(不暂停用户线程,第三个参数启用)的线程数。默认情况下,JVM给定的默认值是ThroughPut垃圾回收的并发数-XX:ParallelGCThreads,
(-XX:ParallelGCThreads + 3)/4。因此,使用
-XX:ParallelGCThreads不仅影响暂停用户阶段的线程数,还影响了并发垃圾回收的并发数。是否可以了解决为,暂停用户线程的GC阶段,使用的线程数是由
-XX:ParallelGCThreads控制的?
5.-XX:CMSInitiatingOccupancyFraction
当堆满的时候(比如没有足够的空间容纳新创建的对象或者没有足够的空间容纳从新生代迁移到老年代的对象),Throughput垃圾回收器会启动一轮GC。但是对于CMS垃圾回收来讲,不应该等到堆满的时候再来执行垃圾回收,因为垃圾回收器执行的同时,应用程序也在执行,此时容易导致内存溢出的问题(应用创建对象的速度大于垃圾回收的速度)。因此,对于CMS垃圾回收器来说,它的回收时机应该提前而不能等到内存即将用完的情况下。
JVM使用-XX:CMSInitiatingOccupancyFraction=<value>指示CMS垃圾回收器开始垃圾回收第一阶段,其中的value指的是老年代的内存使用率。比如
-XX:CMSInitiatingOccupancyFraction=75%,表示当老年代的内存使用率超过75%时,则启动第一阶段的垃圾回收。这个参数的默认值是68,应该是取2/3之意。
6.-XX:+CMSClassUnloadingEnabled
不同于Throughput垃圾回收器,CMS垃圾回收器默认情况下不执行永久代的垃圾回收。如果要对永久代进行垃圾回收,则可以使用-XX:+CMSClassUnloadingEnabled启用永久代垃圾回收。注意:即使没有设置这个选项,当永久代没有可用空间时,GC也会对永久代进行垃圾回收,这个回收的过程是Full GC,因此它不是并发的,也会暂停用户线程
7. -XX:+CMSIncrementalMode
这个选项启用了CMS垃圾回收器的增量模式。增量模式暂停CMS的并发阶段(即GC线程和用户线程同时工作的阶段)以让路给用户线程。因此,CMS垃圾回收器执行完所有的GC阶段将要使用更长的时间。使用这个参数只有在确定的知道CMS GC线程阻扰了用户线程的执行,否则不要设置这个选项,此外,现代的多核服务器完全能够容纳GC和用户线程同时并发
8. -XX:+ExplicitGCInvokesConcurrent and -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
通常,应用通过调用System.gc()来强制进行Full GC是违反最佳实践的做法,这个不论采用使用的垃圾回收算法,显式调用System.gc都是违反最佳实践的做法。这对于CMS垃圾回收来说尤其糟糕,因为System.gc()默认是启动Full GC,这跟CMS GC过程中尽量缩短用户线程的等待时间背道而驰。所幸,JVM提供几个选项来改变这个行为。 -XX:+ExplicitGCInvokesConcurrent选项指示JVM当System GC请求垃圾回收时,JVM应该启动CMS GC而不是默认的Full GC。
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses选项指示JVM在执行System请求的垃圾回收时,一方面执行CMS GC,另一方面也执行永久代的垃圾回收。
9.-XX:+DisableExplicitGC
这个选项用于指示JVM不管垃圾回收采用什么算法,都忽略System.gc()发起的垃圾回收请求。
本文参考https://blog.codecentric.de/en/2013/10/useful-jvm-flags-part-7-cms-collector/
相关推荐
Java虚拟机(JVM)的垃圾回收(Garbage Collection, GC)是Java编程语言中一个重要的特性,它自动管理程序的内存,确保无用的对象被有效地释放,避免内存泄漏。理解JVM垃圾回收机制对于优化Java应用性能至关重要。 ...
Java虚拟机(JVM)的垃圾收集(Garbage Collection, GC)是其内存管理的关键部分,用于自动回收不再使用的对象占用的内存空间。本篇主要介绍了10种不同的垃圾回收器,包括它们的工作原理、优缺点以及适用场景。 1. ...
并发收集则是在应用线程运行的同时进行GC,尽可能减少对应用性能的影响,如CMS(Concurrent Mark Sweep)和G1(Garbage-First)垃圾回收器。 7. G1垃圾回收器 G1是Oracle JDK 1.6引入的一种新的垃圾回收器,它结合...
- **分代收集(Generational GC)**:根据对象的生命周期,将堆分为新生代和老年代,不同年代采用不同的垃圾回收策略。 3. **垃圾回收器**: - **Serial GC**:单线程的垃圾回收器,适合轻量级应用。 - **...
Java虚拟机(JVM)是Java程序运行的基础,它的核心组成部分之一就是垃圾回收(Garbage Collection,简称GC)。GC是JVM自动管理内存的主要方式,它负责识别并清理不再使用的对象,以避免内存泄漏和资源浪费。理解并...
4. **垃圾收集器**:不同的JVM版本提供了不同的垃圾收集器,如Serial、Parallel、CMS(并发标记扫描)、G1(垃圾优先)等。每种收集器有不同的性能特点和适用场景。 5. **GC日志分析**:通过分析JVM产生的GC日志,...
CMS收集器,全称并发标记扫描,是一种用于老年代的垃圾收集器,特别适合于内存大且需要低暂停时间的应用。CMS分为四个阶段:初始标记、并发标记、最终标记和并发清除。在初始和最终标记阶段,GC会暂停应用,但这两个...
JVM的内存管理是其核心功能之一,它涉及到对象的创建、分配、以及释放,而垃圾回收(Garbage Collection, GC)则是内存管理的重要组成部分,用于自动清理不再使用的对象,防止内存泄漏。本文将深入探讨JVM内存结构...
4. CMS GC:并发标记清除,主要处理老年代,尽量减少STW时间,分为初始标记、并发标记、重新标记和并发清除四个阶段。 5. G1 GC:新一代的垃圾回收器,目标是实现低延迟,通过分区技术,可以并发地进行新生代和老...
4. G1 GC:新一代的垃圾回收器,目标是达到低延迟,通过分区技术来平衡吞吐量和暂停时间。 5. ZGC:最新一代的低延迟GC,目标是在大内存环境下实现极低的暂停时间。 四、垃圾回收的过程 GC主要包括三个阶段:标记、...
在JVM的内存模型中,垃圾回收(Garbage Collection, GC)是一项重要的功能,它自动识别并清理不再使用的对象,以释放内存资源。本篇文章将深入探讨JVM中的垃圾回收机制及其各种回收器。 1. **基本概念** - **内存...
8. 使用并发垃圾回收时,年轻代可设置小一些,老年代大一些,因为并发回收不会显著影响其他进程。例如,可以使用-XX:+UseParNewGC来加速年轻代的回收,并配置CMS参数以优化老年代的并发回收。 在具体配置示例中,如...
Java虚拟机(JVM)内存管理和垃圾回收是Java编程中至关重要的概念,它们直接影响着程序的性能和稳定性。本文将详细解析JVM内存结构以及垃圾回收机制。 首先,JVM内存主要分为四个区域: 1. **堆(Heap)**:这是...
- 并发预清理:检查在并发标记期间由年轻代晋升至老年代的对象。 - 重新标记:这个阶段需要暂停应用,快速扫描CMS堆以修正并发标记期间发生变化的对象引用。 - 并发清理:在用户线程运行的同时,清除不可达对象,...
3. **Concurrent Mark Sweep (CMS) GC**:这种垃圾回收器尝试并发地执行大部分垃圾回收操作,以减少"Stop-the-world"事件。它适合响应时间敏感的应用。 4. **G1 (Garbage-First) GC**:G1是一种并行和并发的垃圾...
《JVM性能调优——JVM内存整理及GC回收》是针对Java开发人员的重要主题,尤其是在大型企业级应用中,确保JVM(Java虚拟机)的高效运行是至关重要的。本资料深入探讨了如何通过调整JVM内存设置和优化垃圾回收机制来...
6. **CMS(Concurrent Mark Sweep)收集器**:并发地执行标记和清除,减少Full GC的暂停时间。 7. **G1(Garbage-First)收集器**:新一代的垃圾收集器,目标是达到可预测的停顿时间。 ### **方法调用** 1. **静态...
老年代的空间更大,如果老年代也满了,就会触发Major GC或Full GC,这会清理整个堆内存,包括新生代和老年代。 3. **垃圾收集器(Garbage Collector)**:JVM提供了多种垃圾收集器,如Serial GC、Parallel GC、...
2. Major GC/Full GC:涉及老年代的垃圾回收,可能会导致长时间的系统停顿,应尽量避免频繁发生。 三、垃圾回收器介绍 1. Serial GC:单线程的垃圾回收器,适用于轻量级应用或者低CPU的环境。 2. Parallel GC:多...
JVM的垃圾回收器有多种,如串行GC(Serial GC)、并行GC(Parallel GC)、并发标记扫描GC(CMS, Concurrent Mark Sweep)和G1垃圾收集器等。选择合适的垃圾回收器取决于应用的需求,例如,对于响应时间敏感的应用,...