The Concurrent Mark Sweep (CMS) Garbage Collector was a popular garbage collection algorithm used in the Java Virtual Machine (JVM) for many years. It was introduced to reduce long pause times caused by Full GCs. Although it has been deprecated in newer Java versions (starting from Java 9 and removed in Java 14), many applications still run on older versions of Java that use CMS.
This article will explain the working of CMS in a simple way. It is especially useful for beginners who want to understand how CMS works and when it should be used. CMS is known for doing most of its work alongside (concurrently with) the application, which helps in improving the application’s response time.
What is CMS Garbage Collector?
CMS stands for Concurrent Mark Sweep. It is designed to minimize the pause times during garbage collection by performing most of the work in the background, while the application continues running.
It works mainly on the Old Generation and uses multiple threads to mark and sweep unused objects. The main goal of CMS is to reduce the time the application is stopped during GC. Because of this, CMS is often used in applications where low latency is more important than high throughput.
How CMS Works
The CMS garbage collector divides its work into several phases. Some of these phases pause the application, while others run in the background. Let’s go through each phase:
- Initial Mark (Stop-the-world)
This phase identifies objects that are directly reachable from the root (like static references or thread stacks). It is quick but pauses the application. - Concurrent Mark
This phase finds all other reachable objects by walking through the object graph. It runs at the same time as the application, so there is no stop. - Remark (Stop-the-world)
This phase catches changes made to object references while the concurrent mark was running. It also pauses the application but is optimized to finish quickly. - Concurrent Sweep
The collector now removes unreachable objects and reclaims space. This step also runs with the application still running.
Unlike some other collectors, CMS does not compact memory. This can lead to fragmentation, where there may be enough free memory, but it’s not in one continuous block.
CMS Collection Process
The CMS collection mainly focuses on cleaning the Old Generation space. Here’s how the process works in a step-by-step manner:
1. Minor GC (Young Collection)
- Handled by the Parallel Scavenge or ParNew collector.
- Collects the Young Generation (Eden and Survivor).
- Copies live objects to the Survivor or Old Generation.
2. CMS GC (Old Generation Collection)
- Starts when Old Generation usage crosses a threshold (default is 68%).
- Does most of its work concurrently, reducing pause times.
- Might still cause occasional pauses in Initial Mark and Remark phases.
3. Full GC (Fallback)
- If CMS fails to collect memory in time or the memory is fragmented, a Full GC is triggered.
- This pauses the application completely and compacts memory.

CMS Tuning Parameters
You can tune CMS using various JVM options:
-XX:+UseConcMarkSweepGC
: Enables the CMS collector.-XX:+UseParNewGC
: Uses ParNew for the Young Generation.-XX:CMSInitiatingOccupancyFraction=<n>
: Sets when to start CMS GC (e.g., 70 means 70% of Old Gen usage).-XX:+UseCMSInitiatingOccupancyOnly
: Tells CMS to use only the above threshold.-XX:+CMSClassUnloadingEnabled
: Enables class unloading during CMS GC.-XX:+ExplicitGCInvokesConcurrent
: MakesSystem.gc()
use concurrent collection.
Advantages of CMS GC
CMS offers several benefits for low-latency applications:
- Performs most of the GC work concurrently, minimizing pause times.
- Works well for applications where user experience is critical.
- Allows more predictable and shorter pause times.
- Helps maintain smooth performance for real-time systems.
Limitations of CMS GC
Despite its benefits, CMS has a few downsides:
- It does not compact memory, leading to fragmentation.
- May require more CPU resources during concurrent phases.
- If concurrent phases don’t complete in time, it falls back to Full GC.
- Has been deprecated and removed in newer Java versions.
When to Use CMS GC
CMS is useful in scenarios where:
- Application latency matters more than raw throughput.
- You want to avoid long GC pauses.
- You are using an older Java version (Java 8 or earlier).
- The system has multiple CPU cores to handle concurrent GC threads.
However, if you are using Java 9 or later, it is better to consider G1GC or ZGC, as CMS is no longer supported in newer JVMs.
GC Logs Example (CMS)
Here is a simple example of CMS GC log:
[GC (Allocation Failure) [ParNew: 8192K->1024K(9216K), 0.0034567 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 20480K(30720K)] 21504K(39936K), 0.0012345 secs]
[GC (CMS Final Remark) [YG occupancy: 1024 K (9216 K)] [Rescan (parallel) , 0.0009876 secs] [weak refs processing, 0.0001234 secs] [class unloading, 0.0001234 secs] [scrub symbol table, 0.0001234 secs] [scrub string table, 0.0001234 secs] [1 CMS-remark: 20480K(30720K)] 21504K(39936K), 0.0023456 secs]
- Initial Mark and Final Remark are stop-the-world events.
- Concurrent phases are not shown in detail but run in the background.
- ParNew handles the Young Generation GC.
Conclusion
The Concurrent Mark Sweep (CMS) Garbage Collector was an important GC algorithm for Java applications that needed low pause times and better responsiveness. It performs most of its work concurrently, allowing applications to continue running during major GC activities.
Although CMS has been deprecated and removed in modern JVM versions, it is still important to understand it, especially if you’re working on legacy systems or older Java applications. When used correctly, CMS can greatly improve application performance and user experience.
As a novice, learning how CMS works helps you understand the evolution of garbage collectors in Java and gives you a strong foundation to explore newer collectors like G1GC or ZGC.
You may be interested: