参考 《深入理解Java虚拟机 JVM高级特性与最佳实践》 3.5节
1.垃圾收集器概览
2.Serial收集器
- 使用单线程收集垃圾
- 收集垃圾时,需要停下其他所有工作线程,直到收集结束
- 优点是简单粗暴,效率最高
-
可以跟CMS收集器配合使用
3.ParNew收集器
- ParNew就是Serial收集器的多线程版本
- 可以跟CMS收集器配合使用
- ParNew收集器在单核环境下绝对不会比Serial收集器有更好的效果,因为有线程调度的开销,而这些线程调度的开销下,双核环境下的ParNew收集器的表现都不一定比Serial收集器好
- 解释一下两个名词:
- 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
- 并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。
- 并行和并发的关键区别是否是多个同类线程同时执行。在垃圾收集中,多条垃圾收集线程是同类线程,它们同时执行就是并行,而垃圾收集线程和用户线程就不是同类线程,它们同时执行就是并发。
4.Parallel Scavenge收集器
- 和CMS更关注收集垃圾时的暂停时间相比,Parallel Scavenge(后称PS)更关注吞吐量
- 停顿时间短适合强交互的程序,但是每次的停顿时间短肯定意味着总的停顿时间会变长,而PS的目标就是总的停顿时间最短
5.Serial Old收集器
- Serial收集器的老年代版本
- 单线程收集器,使用“标记-整理”算法
-
在Server模式下,作为CMS收集器的备胎方案,如果CMS并发收集时出现Concurrent Mode Failure时使用
6.Parallel Old收集器
- 注意,这个是Parallel Scavenge收集器的老年代版本,不是ParNew的老年代版本
- 因为之前的情况是使用了Parallel Scavenge收集器的话,就只能使用Serial Old老年代收集器了,这让PS收集器很尴尬,所以又搞了个Parallel Old来配合PS收集器
-
搞了个Parallel Old收集器后,就可以和PS配合使用,这样就可以在吞吐量优先的场景下发挥它们的最大威力
7.CMS(Concurrent Mark Sweep)收集器
- CMS收集器是以最短停顿时间为目标的
- CMS有4个阶段
- 初始标记:标记与GC Roots直接关联的对象们,速度很快,因为只需要标记处于GC Roots关联的第一层对象,需要stop the world
- 并发标记:标记出大部分存活的对象,为什么说是大部分呢,因为这个阶段是并发的,用户线程在标记过程仍然可以使引用链发送改变,不需要stop the world
- 重新标记:因为并发标记是和用户线程一起执行的,而这个阶段可能会有标记结果产生变动的对象,所以需要在这个阶段再进行一次标记,这个阶段会比初始标记慢一点,比并发标记和并发清除快很多,需要stop the world
- 并发清除:不需要stop the world
- CMS的优缺点:
- CMS在并发标记和并发清除的时候会和用户线程分享CPU资源,所以在CPU资源紧张的场合,使用CMS收集器可能会降低程度的速度
- CMS无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC产生。浮动垃圾是怎么产生的呢?因为在垃圾回收的最后阶段,也就是并发清除过程中,用户线程仍然可以产生垃圾!这些垃圾已经无法在本轮GC中被回收,就是所谓的浮动垃圾,如果这些垃圾的量很大,而剩余的空间又不足的话,就会引发“Concurrent Mode Failure”,然后使用Serial Old作为替代方案进行垃圾收集。所以老年代一般不会设定为满了才开始垃圾回收,要是这样的话百分百会导致“Concurrent Mode Failure”,想想啊,要是你满了才开始回收,那用户线程产生的垃圾放哪里?可以通过设置-XX:CMSInitiatingOccupancyFraction来设置出发老年代垃圾回收的百分比。
- CMS是基于“标记- 清除”算法实现的收集器,这样的收集器都会有一个毛病,就是回产生大量的内存碎片,那既然会产生内存碎片,那为什么不用“标记-整理”算法呢,因为“标记-整理”算法的整理过程是需要stop the world的!这和CMS的设计理念(尽可能短的暂停时间)相悖,所以没有使用“标记-整理”算法。为了解决这个问题,CMS提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认开启),当CMS收集器顶不住要进行FullGCT时开启内存碎片的合并并整理过程。还有一个参数-XX:CMSFullGCsBeforeCompaction设置执行多少次不压缩的Full GC后,跟着一次带压缩的整理。
8.G1收集器感觉说的不是很清楚,就是草草介绍了一下
9.理解GC日志
直接看书里的好了,就是一些规则