这是一款跨时代的垃圾收集器,真正做到了垃圾收集线程与用户线程(基本上)同时工作。和 Serial 收集器的 Stop The World(妈妈打扫房间的时候,你不能再将垃圾丢到地上) 相比,真正做到了妈妈一边打扫房间,你一边丢垃圾。
①、作用于老年代
②、多线程
③、使用标记-清除算法
整个算法过程分为如下 4 步:
一、初始标记(CMS initial mark):只是仅仅标记GC Root 能够直接关联的对象,速度很快,但是需要“Stop The World”
二、并发标记(CMS concurrent mark):进行GC Root Tracing的过程,简单来说就是遍历Initial Marking阶段标记出来的存活对象,然后继续递归标记这些对象可达的对象。
三、重新标记(CMS Remark):修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,需要“Stop The World”。这个时间一般比初始标记长,但是远比并发标记时间短。
四、并发清除(CMS concurrent sweep):对上一步标记的对象进行清除操作。
由于整个过程最耗时的操作是第二(并发标记)、四步(并发清除),而这两步垃圾收集器线程是可以和用户线程一起工作的。所以整体来说,CMS垃圾收集和用户线程是一起并发的执行的。
缺点:
①、对CPU资源敏感
因为在并发阶段,会占用一部分CPU资源,从而导致应用程序变慢,总吞吐量会降低。
②、产生浮动垃圾
由于CMS并发清理阶段用户线程还在工作,这个时候产生的垃圾,CMS无法在本次收集中处理掉它们,只能留在下一次GC时再将其处理掉,这部分垃圾称为“浮动垃圾”。
③、产生内存垃圾碎片
因为采用的算法是标记-清除,很明显,会有空间碎片产生。
8、G1收集器这是当前收集器技术发展的最前沿的成果。可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收。
这是因为它并不像前面介绍的所有垃圾收集器是区分新生代,老年代的,它作用于全区域。将整个Java堆划分为多个大小固定的独立区域(Regin),并且跟踪这些区域的垃圾堆积面积,在后台维护一个优先级列表,每次根据允许的收集时间,优先回收垃圾最多的区域,这样保证了G1收集器在有限的时间内可以获得最高的收集效率。
它与前面讲的 CMS 垃圾收集器相比,有两个显著的改进:
①、采用 标记-整理 的回收算法
这样不会产生空间碎片
②、可以精确的控制停顿时间
能让使用者明确指定一个长度为M毫秒的时间片内,消耗在垃圾回收上的时间不超过 N 毫秒。
③、作用于整个Java堆
G1收集器不区分年轻代和老年代,是整堆垃圾收集器。
9、如何选择垃圾收集器详细文档可以查看官方介绍,如下
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html
这里我们翻译一下结论:
除非应用程序有相当严格的暂停时间要求,否则就让JVM自己选择垃圾收集器。并且可以适当优先调整堆的大小来提高性能。如果还不满足要求,则以下面四点作为指导:
1. 如果应用程序内存小于100M,那么使用选项选择串行收集器-XX:+UseSerialGC。
2. 如果应用程序将在单核处理器上运行,并且没有停顿时间的要求,选择串行-XX:+UseSerialGC或者 JVM 自己选
3. 如果允许停顿时间超过1秒,选择并行或 JVM 自己选