什么是CMS垃圾收集器?它的垃圾回收过程是什么样子的?
3 个回答
你要习惯任何人的忽冷忽然,也要看淡任何人的渐行渐远。唐三藏**CMS**(Concurrent Mark-Sweep)是 **Java 老年代(Old Generation)**的一种垃圾收集器,采用**标记-清除(Mark-Sweep)**算法。在垃圾回收过程中,它将对象标记为可达或不可达,并清除不可达的对象来回收内存。下面详细解释 CMS 各个步骤的含义及其作用。 ## **1. 初始标记(Initial Mark)** - **含义**: - **标记所有直接与 GC Root 相连的对象**。这些对象是从根集合(GC Roots)出发的第一层对象。 - **GC Root** 通常包括以下几类对象: - 栈中的局部变量。 - 当前执行的线程中的变量。 - 类的静态字段。 - **特点**: - 这是 **STW(Stop-the-World)** 阶段,即应用程序的所有线程会**暂停**,但时间很短。 - 由于只是标记与 GC Root 直接相连的对象,**操作量少,暂停时间短**。 ## **2. 并发标记(Concurrent Mark)** - **含义**: - **从初始标记的对象出发**,递归标记**所有与之可达的对象**。 - 标记可达的对象,找出哪些对象是“活着的”,哪些对象是“垃圾”。 - **特点**: - 该阶段与**应用程序线程并发执行**,即应用程序不会停止运行。 - CMS 收集器会在后台扫描内存中所有存活的对象。这部分时间较长,因为涉及深度遍历对象引用图。 ## **3. 重新标记(Remark)** - **含义**: - 由于**并发标记阶段**应用程序仍在运行,期间对象的引用关系可能发生了变化,导致部分对象标记不准确。 - **重新扫描**这些变化过的对象,更新标记状态,确保标记的正确性。 - **特点**: - 该阶段也会暂停应用程序线程(STW),但由于只处理少量变化的对象,**暂停时间较短**。 - 这是保证垃圾回收准确性的重要步骤。 ## **4. 并发清除(Concurrent Sweep)** - **含义**: - 在这一阶段,CMS 会扫描整个堆,**清除未标记的对象**,释放它们占用的内存空间。 - **特点**: - **与应用程序线程并发进行**,无需暂停应用程序。 - 该阶段的主要工作是将标记为“垃圾”的对象空间释放,以便后续分配新对象使用。 ### **CMS 回收的关键点** 1. **STW(Stop-the-World)阶段**: - **初始标记**和**重新标记**需要短暂的 STW。 - CMS 设计的初衷就是尽量减少应用线程的停顿时间,因此 STW 只在这两阶段发生。 2. **与应用线程并发**: - **并发标记**和**并发清除**阶段与应用程序线程一起执行,最大限度减少了对程序运行的影响。 3. **缺点**: - **浮动垃圾(Floating Garbage)**: - 由于 CMS 与应用程序并发执行,一些对象可能在标记阶段结束后才变为垃圾,这些对象不会被当前回收周期处理,需要等下一个回收周期清理。 - **内存碎片**: - CMS 采用的是标记-清除算法,不会对内存进行整理,可能产生大量**内存碎片**。 ### **CMS 垃圾回收流程图** ```plaintext 初始标记(STW) ----> 并发标记 ----> 重新标记(STW) ----> 并发清除 | | | |<----- 与应用线程并发 ---->|<----- 与应用线程并发 ----->| ``` ### **总结** CMS 垃圾回收的四个步骤: 1. **初始标记**:标记与 GC Root 直接相连的对象(短暂 STW)。 2. **并发标记**:从初始标记的对象出发,递归标记所有可达对象(与应用线程并发)。 3. **重新标记**:修正并发标记阶段的引用变化(短暂 STW)。 4. **并发清除**:清理未标记的垃圾对象(与应用线程并发)。 CMS 的优点是**减少应用停顿时间**,但也会产生**浮动垃圾**和**内存碎片**的问题。在需要低延迟的场景中,CMS 是一个常用的垃圾收集器,但它也逐渐被 **G1(Garbage First)** 收集器所替代,后者在一定程度上解决了 CMS 的缺点。编辑于 2024-09-28 02:19 •IP属地 美国举报评论收藏
热爱漫无边际,生活自有分寸。亚林CMS(Concurrent Mark-Sweep)垃圾收集器是Java虚拟机(JVM)中的一种**低延迟**的垃圾收集器,适用于减少垃圾回收过程中应用程序暂停时间的场景,特别是对那些需要高响应的应用程序。CMS 是 JDK 1.5 引入的,它是一个基于标记-清除算法的垃圾收集器,适用于老年代的垃圾回收。 ### CMS垃圾收集器的特点: - **并发收集**:CMS与应用线程并发执行垃圾回收操作,尽量减少应用程序的暂停时间(Stop-The-World,STW)。 - **低延迟**:CMS 的主要目标是减少老年代的回收时间,因此适合那些对延迟敏感的应用场景,例如需要快速响应的互联网应用。 - **"Stop-The-World" 仍然存在**:虽然 CMS 的设计初衷是减少暂停时间,但它在某些阶段仍然需要暂停所有应用线程。 ### CMS垃圾收集算法 CMS 使用的是**标记-清除算法**,该算法包含两个阶段: 1. **标记(Marking)**:标记出所有存活的对象。 2. **清除(Sweeping)**:清除掉未标记的垃圾对象,释放内存。 ### CMS垃圾收集器的工作流程 CMS 的垃圾回收过程可以分为以下四个步骤: 1. **初始标记(Initial Mark)**: - 标记所有**直接与GC Root**相连的对象。 - 该阶段需要暂停应用程序线程(STW),但时间很短,因为只标记GC Root对象。 2. **并发标记(Concurrent Mark)**: - 在此阶段,CMS 会**和应用程序并发地进行**,追踪从初始标记阶段标记的根对象开始可达的对象。 - 该阶段不需要暂停应用程序线程。 3. **重新标记(Remark)**: - 由于并发标记阶段,应用程序仍在运行,可能会有一些对象的引用关系发生变化,因此需要重新扫描这些对象并进行标记更新。 - 这个阶段同样需要暂停应用程序线程,但时间较短。 4. **并发清除(Concurrent Sweep)**: - 清除未标记的对象并回收相应的内存空间。 - 这个阶段不需要暂停应用程序线程,依旧与应用程序并发进行。 ### CMS 标记过程: - **初始标记**阶段快速标记GC Root对象。 - **并发标记**阶段遍历整个对象图,标记从GC Root开始的可达对象。 - **重新标记**阶段处理并发标记时可能错过的对象,并确保标记准确。 - **并发清除**阶段释放内存,不标记的对象将被认为是垃圾并被清除。 ### CMS的缺点 尽管 CMS 能减少老年代的垃圾回收停顿时间,但它也有一些缺点: 1. **浮动垃圾(Floating Garbage)**:由于 CMS 并发清理的特点,在清理过程中可能会有新的垃圾产生,导致这些垃圾无法被立即回收,需要等到下次 GC。 2. **内存碎片化**:CMS 使用的标记-清除算法会导致内存碎片化,可能无法找到连续的内存空间来分配大对象,导致出现**“Concurrent Mode Failure”**,进而触发一次完全的 Stop-The-World(STW)全堆垃圾回收(Full GC)。 3. **高CPU消耗**:由于 CMS 需要与应用程序线程并发执行回收操作,所以对 CPU 资源要求较高。 ### CMS使用的**标记-清除算法** CMS 的垃圾回收流程主要是通过**标记-清除**来实现的,即: 1. **标记**:标记出所有存活的对象。 2. **清除**:直接清理掉未标记的垃圾对象,并释放相应的内存。 CMS 并没有做“整理”操作,这意味着它只是清除不再使用的对象,而不会像标记-整理算法那样把存活的对象压缩到一起。**因此,CMS 的回收会导致内存碎片化**。 ### 标记-清除 vs 标记-整理 - **标记-清除**: - 这种算法在标记阶段标记存活的对象,然后直接清理掉那些未标记的对象。 - 结果是,**内存不会连续**,可能出现很多小的内存碎片,特别是在回收长时间运行的程序时,内存碎片化问题会更加明显。 - CMS 就是这种方式,因为它不会移动存活对象的内存位置。 - **标记-整理**: - 标记-整理算法在标记存活对象后,不仅会清理垃圾对象,还会**移动存活对象**,将它们整理到一起,使得内存变得连续,避免碎片化问题。 - G1垃圾收集器和一些其他现代垃圾收集器使用了标记-整理算法,避免了内存碎片化问题。 ### 为什么CMS不使用标记-整理? - **并发执行**:CMS 的目标是减少应用程序的暂停时间,因此它通过并发标记和清理操作来实现,这让它不能频繁地进行对象移动。对象移动需要暂停所有线程,并进行数据的调整,这样就违背了 CMS 低延迟、减少暂停时间的设计目标。 - **内存碎片化问题**:正因为 CMS 只做标记和清除,不做整理,因此会产生内存碎片。如果内存碎片过多,会导致系统无法分配大块内存,从而引发 `Concurrent Mode Failure`,并最终导致一次 `Full GC`,这会造成较长时间的 STW 暂停。 ### 标记-整理的垃圾收集器 相比之下,现代的垃圾收集器如 **G1** 或 **ZGC** 采用了标记-整理算法,它们在回收时不仅标记存活对象,还会移动存活对象,使得内存更加连续,避免内存碎片化问题。 总结: - **CMS** 使用的是 **标记-清除** 算法,不会对内存进行整理,因此会产生内存碎片。 - **标记-整理** 算法则是另一种更现代的回收方式,它会移动存活对象并整理内存,从而减少碎片化,但代价是更长的暂停时间。 ### 总结: CMS 是一种为了减少垃圾回收停顿时间而设计的并发垃圾收集器,采用**标记-清除算法**。其标记过程分为初始标记、并发标记、重新标记、并发清除四个阶段,但由于浮动垃圾和内存碎片等问题,CMS 也有一些局限性。发布于 2022-05-27 20:09 •IP属地 天津举报评论收藏
生活就是这样,别人看到的是结果,而自己撑的是整个过程。Hobbit霍比特人CMS是老年代垃圾收集器,在收集过程中可以与用户线程并发操作。它可以与Serial收集器和Parallel New收集器搭配使用。CMS牺牲了系统的吞吐量来追求收集速度,适合追求垃圾收集速度的服务器上。可以通过JVM启动参数:-XX:+UseConcMarkSweepGC来开启CMS。 CMS收集过程 CMS 处理过程有七个步骤: 初始标记(CMS-initial-mark) ,会导致stw; 并发标记(CMS-concurrent-mark),与用户线程同时运行; 预清理(CMS-concurrent-preclean),与用户线程同时运行; 可被终止的预清理(CMS-concurrent-abortable-preclean) 与用户线程同时运行; 重新标记(CMS-remark) ,会导致swt; 并发清除(CMS-concurrent-sweep),与用户线程同时运行; 并发重置状态等待下次CMS的触发(CMS-concurrent-reset),与用户线程同时运行; 其运行流程图如下所示:  CMS收集器只收集老年代,其以吞吐量为代价换取收集速度。 CMS收集过程分为:初始标记、并发标记、预清理阶段、可终止预清理、重新标记和并发清理阶段。其中初始标记和重新标记是STW的。CMS大部分时间都花费在重新标记阶段,可以让虚拟机先进行一次Young GC,减少停顿时间。CMS无法解决"浮动垃圾"问题。 由于CMS的收集线程和用户线程并发,可能在收集过程中出现"concurrent mode failure",解决方法是让CMS尽早GC。在一定次数的Full GC之后让CMS对内存做一次压缩,减少内存碎片,防止年轻代对象晋升到老年代时因为内存碎片问题导致晋升失败。发布于 2022-03-13 12:36 •IP属地 辽宁举报评论收藏
公众号进入网站体验更佳

