jvm中的不同垃圾收集器特点以及区别
新生代 GC(Minor GC)
一、Serial(串行)收集器
![](https://img-blog.csdnimg.cn/img_convert/48af2ceb8d34af5fbfef56ace0e99116.png)
1.特点
● 针对新生代的收集器;
● 采用复制算法; 单线程收集;
● 进行垃圾收集时,必须暂停所有工作线程,直到完成; 即会"Stop The World";
2.应用场景
● 依然是HotSpot在Client模式下默认的新生代收集器;
● 也有优于其他收集器的地方: 简单高效(与其他收集器的单线程相比);
● 对于限定单个CPU的环境来说,Serial收集器没有线程交互(切换)开销,可以获得最高的单线程收集效率;
● 在用户的桌面应用场景中,可用内存一般不大(几十M至一两百M),可以在较短时间完成垃圾收集(几十MS至一百多MS),只要不频繁发生,这是可以接受的
二、ParNew收集器(Serial收集器的多线程版本-使用多条线程进行GC)
![](https://img-blog.csdnimg.cn/img_convert/68ff9f2485d12bec0fb7e1014e6613bd.png)
1.特点
● 除了多线程外,其余的行为、特点和Serial收集器一样;
2.应用场景
● 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作;
● 但在单个CPU环境中,不会比Serail收集器有更好的效果,因为存在线程交互开销。
三、Parallel Scavenge收集器
![](https://img-blog.csdnimg.cn/img_convert/e2b909cada8013d3ff95612c534b9676.png)
1.特点
● 新生代收集器;采用复制算法;
● 多线程收集;
● CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间;而Parallel Scavenge收集器的目标则是达一个可控制的吞吐量(Throughput);
● GC自适应的调节策略(GC Ergonomics)
2.应用场景
● 高吞吐量为目标,即减少垃圾收集时间,让用户代码获得更长的运行时间;
● 当应用程序运行在具有多个CPU上,对暂停时间没有特别高的要求时,即程序主要在后台进行计算,而不需要与用户进行太多交互;
● 例如,那些执行批量处理、订单处理(对账等)、工资支付、科学计算的应用程序;
老年代 GC(Major GC/Full GC)
一、Serial Old收集器
1.特点
● 针对老年代;
● 采用"标记-整理-压缩"算法(Mark-Sweep-Compact);
● 单线程收集; Serial/Serial Old收集器运行示意图在前面有。
2.应用场景
● 主要用于Client模式;
● 而在Server模式有两大用途:
(A)、在JDK1.5及之前,与Parallel Scavenge收集器搭配使用(JDK1.6有Parallel Old收集器可搭配Parallel Scavenge收集器);
(B)、作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用;
二、Parallel Old收集器
![](https://img-blog.csdnimg.cn/img_convert/aed2bde53691d9ad7d57bcbc196a4cc0.png)
1.特点
● 针对老年代;采用"标记-整理-压缩"算法;
● 多线程收集;
2.应用场景
● JDK1.6及之后用来代替老年代的Serial Old收集器;
● 特别是在Server模式,多CPU的情况下:
○ 这样在注重吞吐量以及CPU资源敏感的场景,就有了Parallel Scavenge(新生代)加Parallel Old(老年代)收集器的"给力"应用组合;
三、CMS(Concurrent Mark Sweep)收集器
![](https://img-blog.csdnimg.cn/img_convert/3a42fdeb06acd9b64dac3216cf4f8334.png)
1.特点
● 针对老年代
● 基于"标记-清除"算法(不进行压缩操作,会产生内存碎片)
● 以获取最短回收停顿时间为目标
● 并发收集、低停顿
● 需要更多的内存
2.应用场景
● 与用户交互较多的场景;(如常见WEB、B/S-浏览器/服务器模式系统的服务器上的应用)
● 希望系统停顿时间最短,注重服务的响应速度;以给用户带来较好的体验;
3.CMS收集器运作过程
● 初始标记:
○ 暂停所有的其他线程,初始标记仅仅标记GC Roots能直接关联到的对象,速度很快;
● 并发标记
○ 并发标记就是进行GC Roots Tracing的过程;
○ 同时开启GC和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以GC线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方;
● 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录(采用多线程并行执行来提升效率);需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短;
● 并发清除: 开启用户线程,同时GC线程开始对为标记的区域做清扫,回收所有的垃圾对象;
4.缺点
● 对CPU资源敏感;导致应用程序变慢,总吞吐量会降低
● 无法处理浮动垃圾;在并发清除时,用户线程新产生的垃圾,称为浮动垃圾;
○ 设置CMS预留老年代内存空间解决;
● 产生大量内存碎片;基于“标记+清除”算法
○ CMS收集器提供−XX:+UseCMSCompactAlFullCollection标志,使得CMS出现上面这种情况时不进行Full GC,而开启内存碎片的合并整理过程;
G1收集器(不区分新生代和老生代)
![](https://img-blog.csdnimg.cn/img_convert/6320b6c9e26b382aa529c4551449bc85.png)
1.特点
(1)并行与并发
● 其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。
(2)分代收集
● 能独立管理整个GC堆(新生代和老年代),而不需要与其他收集器搭配;
● 能够采用不同方式处理不同时期的对象;
● 虽然保留分代概念,但Java堆的内存布局有很大差别;
● 将整个堆划分为多个大小相等的独立区域(Region);
● 新生代和老年代不再是物理隔离,它们都是一部分Region(不需要连续)的集合;
(3)空间整合
● 从整体看,是基于标记-整理算法;
● 从局部(两个Region间)看,是基于复制算法;
● 这是一种类似火车算法的实现; 不会产生内存碎片,有利于长时间运行;(火车算法是分代收集器所用的算法,目的是在成熟对象空间中提供限定 时间的渐进收集。)
(4)可预测的停顿
● G1除了追求低停顿外,还能建立可预测的停顿时间模型。明确指定M毫秒时间片内,垃圾收集消耗的时间不超过N毫秒。在低停顿的同时实现高吞吐量
2.应用场景
● 面向服务端应用,针对具有大内存、多处理器的机器;
● 最主要的应用是为需要低GC延迟,并具有大堆的应用程序提供解决方案;
○ 如:在堆大小约6GB或更大时,可预测的暂停时间可以低于0.5秒; (实践:对账系统中将CMS垃圾收集器修改为G1,降低对账时间20秒以上)