笔记目录
1.分代收集理论
现代大部分的虚拟机的垃圾回收器都遵循“分代收集”的理论基础来进行设计实现:
- 绝大部分的对象的声明周期很短,都是朝生夕死。
- 历经多次垃圾回收后仍然存活的对象就可能更加越难被回收。
根据这个理论基础,JVM的大部分虚拟机将堆空间逻辑划分为新生代/年轻代、老年代,垃圾收集器可以根据不同的区域选择不同的回收算法进行GC。
2.垃圾回收算法
2.1 标记-复制算法
复制算法
将内存分隔为两块相同大小的区域,每次只使用其中的一块,每当GC完成后,将存活的对象复制到另一块区域,然后将前一块清空。
2.2 标记-清除算法
标记-清除法
分为标记和清除两个阶段,标记存活的对象,然后GC清除掉没有被标记的对象。这种算法实现简单,但是有2个缺点:
- 内存越大,要标记的对象越多,耗时越久,性能越低。
- 内存碎片化问题,导致大对象(数组)分配困难。
2.3 标记-整理算法
标记-整理法
大体流程和标记清除法一致,但是它具有整理内存空间的功能。这种算法避免了内存碎片化的问题,但是效率上相对于标记-清除法略低。
一般情况下,年轻代大多采用标记-复制算法,而老年代则标记-清除和标记-整理算法都有,不同垃圾收集器的实现方案不一样。
2.常见垃圾收集器
3.Serial、Serial Old收集器组合(最古老、现在几乎不主动用)
Serial
和Serial Old
在JVM早期就诞生了,他俩的特点如下:
- 单线程工作模式
- GC期间用户线程暂停,STW一般控制在百级毫秒左右
- 适合几十到几百兆的堆内存使用,内存越大,这两者的回收效果越差
- 现在基本上不会用到他俩,-XX:+UseSerialGC、-XX:+UseSerialOldGC可以开启
4.Parallel Scavenge、Parallel Old(JDK8默认的收集器)
Parallel Scavenge
和Parallel Old
收集器已经是JDK8默认的组合,也是第一款并发收集器,特点:
- GC过程采用多线程模式,线程数可配置,默认是CPU核心数`-XX:ParallelGCThreads`
- 可配置`-XX:MaxGCPauseMillis`,控制GC暂停的最大时间,但吞吐量会降低,因为GC更频繁。
- 他俩更关注JVM系统的吞吐量
5.ParNew收集器(通常配合CMS)
ParNew
和Parallel Scavenge很相似,都是并发执行GC工作,但是ParNew只能负责新生代的GC任务。
6.CMS收集器(划时代意义的一款收集器)
Concurrent Mark Sweep
简称CMS,这是一款追求低延时的收集器,也是第一款真正意义上的并发垃圾收集器,它实现了GC线程和用户线程同时工作的能力,极大提高了JVM垃圾收集的亲和力;但是CMS也是唯一一款采用标记-清除算法的老年代收集器。
CMS整个工作流程分为5个阶段:
6.1 阶段一:初始标记
初始标记
阶段将GC Roots作为根节点扫码与之直连的对象,速度较快耗时很短,但是会暂停用户线程STW。
6.2 阶段二:并发标记
并发标记
阶段从GC Roots直连的对象作为开始,通过可达性分析算法扫码整个堆,这个过程很长,但是可以和用户线程并发执行,所以没有STW。但是并发标记阶段会存在多标、漏标的问题。
6.3 阶段三:重新标记
重新标记