垃圾回收算法与垃圾收集器
文章目录
- 一、垃圾回收算法
- 1. 标记-清除算法
- 2. 复制算法
- 3. 标记-整理算法
- 二、垃圾收集器
- 新生代收集器
- 1. Serial收集器
- 2. ParNew收集器
- 3. Parallel Scavenge收集器
- 老年代收集器
- 1. Serial Old收集器
- 2. Parallel Old收集器
- 3. CMS收集器
- G1收集器
- 概念特点
- G1的工作流程
- G1的优势
- 三、算法与收集器的对应关系
一、垃圾回收算法
1. 标记-清除算法
工作流程:
第一阶段:标记出所有需要回收的对象
第二阶段:清除统一回收所有被标记的对象
优缺点:
- 优点:实现简单,适用于存活对象多的场景
- 缺点:会产生内存碎片,效率不稳定
2. 复制算法
工作流程:
将内存分为两块相等区域
只使用其中一块,另一块闲置
GC时将存活对象复制到闲置区域
清空原使用区域,两块区域角色互换
优缺点:
- 优点:无内存碎片,效率高
- 缺点:浪费一半内存空间,以空间换时间
3. 标记-整理算法
工作流程:
第一阶段:标记所有存活对象
第二阶段:将存活对象向内存一端移动
第三阶段:清理掉边界以外的内存
优缺点:
- 优点:无内存碎片,内存利用率高
- 缺点:移动对象成本高,效率较低
二、垃圾收集器
新生代收集器
1. Serial收集器
特点:
- GC时会暂停所有用户线程(Stop The World)
- 单线程执行垃圾回收
- 回收完成后恢复用户线程
2. ParNew收集器
特点:
- 多线程并行收集
- 其他行为与Serial完全一样
- 常与CMS搭配使用
3. Parallel Scavenge收集器
特点:
- 可控制的吞吐量(运行代码时间/(运行代码时间+GC时间))
- 自适应调节策略
- 目标是达到可控的吞吐量
老年代收集器
1. Serial Old收集器
这是Serial收集器的老年代版本:
还是单线程工作
使用标记-整理算法
主要用在客户端程序上
2. Parallel Old收集器
这是Parallel Scavenge的搭档:
多线程并行工作
同样使用标记-整理算法
和Parallel Scavenge一起使用,整体注重吞吐量
3. CMS收集器
CMS全称是Concurrent Mark Sweep,意思是并发标记清除,这是个很有特色的收集器:
工作流程比较复杂:
初始标记:快速标记一下根源对象,这个过程需要暂停程序
并发标记:一边让程序正常跑,一边慢慢标记所有要清理的对象
重新标记:再暂停一下程序,修正错标、漏标的对象
并发清除:一边让程序跑,一边清理垃圾
CMS的缺点:
- 在并发标记阶段会和用户线程争抢CPU资源,影响用户线程的执行效率
- 清理过程中还在产生新垃圾(浮动垃圾),有些垃圾这次清理不了,得放到下一次GC
- 使用标记-清除算法,会产生内存碎片
G1收集器
概念特点
G1是Garbage First的缩写,这是目前比较先进的收集器:
- 把整个内存分成很多小块(Region),每块通常1-32MB
- 每个小块可以分别当作新生代或老年代来用
- 每次清理的时候,会根据垃圾最多、回收效益最高的的几个小块来清理
G1的工作流程
初始标记:快速标记根源对象,需要暂停程序
并发标记:程序正常跑的同时进行标记工作
最终标记:暂停程序,处理并发期间的变化
筛选回收:暂停程序,选择最值得清理的区域进行回收
G1的优势
- 可以设定目标暂停时间,比如希望每次暂停不超过200毫秒
- 内存利用率高,没有传统分代收集器的空间浪费
- GC时不会产生内存碎片
- 适合大内存应用,可以处理几个G到几十G的堆内存
三、算法与收集器的对应关系
收集器 | 算法选择 | 适用场景 |
---|---|---|
Serial | 复制(新生代) | 单核CPU,小应用 |
ParNew | 复制(新生代) | 多核CPU,配合CMS |
Parallel Scavenge | 复制(新生代) | 注重吞吐量 |
Serial Old | 标记-整理(老年代) | 单核CPU,小应用 |
Parallel Old | 标记-整理(老年代) | 注重吞吐量 |
CMS | 标记-清除(老年代) | 注重响应时间 |
G1 | 复制+标记-整理 | 大堆内存,低延迟要求 |