- 什么是垃圾收集器
- 垃圾收集器的种类
- CMS收集器
- 清理范围
- 特点
- 垃圾回收过程
- 问题
- 内存碎片
- 并发失败/Concurrent mode failure
- 晋升失败/promotion failed
- 浮动垃圾
- 重新标记过程耗时长
- G1收集器
- 清理范围
- 特点
从内存中清理垃圾的具体步骤
垃圾收集器的种类| 回收范围 | 回收算法 | 是否 需要 暂停 用户 线程 | 应用场景 | ||||
|---|---|---|---|---|---|---|---|
| Serial / 新生代串行收集 | 新生代 | 复制算法 | 是 | 单线程 | 串行 | Client模式 | 单CPU场景下,新生代空间小的时候,收集耗费的时间少,停顿时间少 |
| ParNew收集器 / 新生代并行收集器 | 新生代 | 复制算法 | 是 | 多线程 | 并行 | 多CPU场景下,新生代空间小的时候,收集耗费的时间少,停顿时间少 | |
| Parallel Scavnge收集器 | 新生代 | 复制算法 | 是 | 多线程 | 并行 | 自行配置回收多少垃圾,回收时间长那么回收垃圾多,回收时间少回收垃圾少,回收垃圾的数量与回收垃圾的时间是成比例的 | 可控制的吞吐量。要求多回收垃圾的时候,高效利用CPU时间。要求回收垃圾时间短的时候,良好的响应速度,提升用户体验。 |
| Serial Old收集器 / 老年代串行收集器 | 老年代 | 标记-压缩 | 是 | 单线程 | 串行 | 适用于Client模式 | |
| Parallel Old收集器 / 老年代并行收集器 | 老年代 | 标记-压缩 | 是 | 多线程 | 并行 | 自行配置回收多少垃圾,回收时间长那么回收垃圾多,回收时间少回收垃圾少,回收垃圾的数量与回收垃圾的时间是成比例的 | 可控制的吞吐量。要求多回收垃圾的时候,高效利用CPU时间。要求回收垃圾时间短的时候,良好的响应速度,提升用户体验。 |
| CMS收集器 / Concurrent Mark Sweep | 老年代 | 标记-清除 | 不需要 | 多线程 | B/S系统的服务端,互联网站 | 最短回收停顿时间 | |
| G1收集器 | 整个堆内存 | 不区分新生代和老年代,总体是标记压缩,局部用复制算法 | 不需要 | 多线程 |
回收老年代内存空间
特点1.重新标记过程,用户线程需要暂停,大约消耗了80%时间
2.相当于是并发垃圾收集器,相对于其他垃圾收集器,用户线程停顿时间大幅减少
3.初始标记和重新标记过程,是需要暂停用户线程的
1.初始标记
2.并发标记
3.预清理
4.可被终止的清理
5.重新标记
6.并发清除
7.并发重置状态下等待下次CMS触发
现象
因为CMS是用的是标记-清除算法,导致连续内存空间不够多,从而导致老年代剩余空间足以容纳要放入老年代的对象,但由于剩余的内存空间不是连续的,而且剩余的连续空间是不足以容纳要放入老年代的对象的,于是引发了full GC,full GC的时候是需要暂停用户线程的,因此导致GC停顿时间变长
解决方案
1.老年代定期进行内存碎片整理
可以通过参数指定经过多少次full GC会对老年代内存碎片进行压缩
0次表示要进行full GC的时候就会对老年代内存碎片进行压缩
并发失败/Concurrent mode failure现象
所有并发的过程都可能出现这种情况
并发清除的时候用户线程还在继续运行,就会产生年轻代对象在GC之前向老年代放入了新对象的情况,那么可能在CMS垃圾收集器对老年代进行清理之前,老年代已经满了,导致对象晋升老年代失败,引发了FullGC,从而引起用户线程暂停,导致GC停顿时间变长
这里的主要关注点是并发,也就是由CMS GC与用户线程并发,导致老年代满了,至于是什么原因向老年代放入对象,并不是关注点,向老年代放入对象的原因可能是年轻代对象提前晋升老年代,也可能是年轻代对象正常晋升到老年代
解决方案
1.指定老年代占用达到一定比例时就进行GC,为CMS GC执行时因用户线程并发执行向老年代放入对象预留一些空间,而不是等待老年代满了再进行老年代GC
晋升失败/promotion failed现象
老年代放不下新生代晋升上来的对象引发Full GC
这里的关注点是从年轻代晋升上来的对象在老年代放不下
解决方案
1.老年代定期在full GC后进行碎片整理
避免因为老年代连续内存空间不足导致晋升失败引发Full GC
2.降低老年代GC阈值
触发老年代GC的空间占用比例降低,老年代GC发生更加频繁
3.增大幸存区大小
减少对象从年轻代晋升老年代
由于并发产生的新垃圾没有被标记在本次老年代GC清理范围内
重新标记过程耗时长重新标记节点数对老年代对象进行标记,标记的是存活对象,即使新生代对象已经不可达了,但是如果老年带对象被新生代对象引用,也会被标记
于是可以在重新标记之前进行新生代垃圾回收,可以通过收集器参数启用该功能
G1收集器 清理范围整个堆内存(包括年轻代和老年代)
特点1.堆内存回收器,回收范围是整个堆内存
2.将堆内存划分为多个Region,Region分为4种类型
3.Region的类型
E区:eden区
S区:幸存区
O区:老年代
H区:存放大对象
4.Region的大小为1-32MB
默认是将堆内存划分为2048份,每份的大小就是每个Region的大小
5.与默认的对象分配规律大体相同
不同的是,如果对象的大小超过Region的一半,会在H区为对象分配内存空间,而不是年轻代或者老年代
6.相当于是并发垃圾收集器,相对于其他垃圾收集器,用户线程停顿时间大幅减少
7.GC过程中有些环节仍然是要暂停用户线程的



