JVM的垃圾回收
# 前言
垃圾的定义: 不再被引用的对象就是垃圾。 那如何判断一个对象是否被引用呢?
- 引用计数法 用一个标记记录引用次数,当引用次数为0时,就是垃圾
- 可达性分析法 从GC Roots开始,遍历所有对象,如果对象不可达,就是垃圾。
# 垃圾回收算法
- 标记-清除算法 先标记好回收的对象,然后统一回收
- 标记-压缩算法 标记好回收的对象,然后将存活的对象压缩到一端,然后回收另一端的空间
- 复制算法 将内存分为两块,每次只使用一块,当这一块满了,就将存活的对象复制到另一块,然后回收这一块
- 分代算法 根据对象的存活周期将内存分为不同的区域,然后根据不同的区域使用不同的算法
# 垃圾回收器
垃圾回收器是实现垃圾回收算法的具体实现,根据不同的算法和实现,可以分为以下几种 先看一张图,了解一下各个垃圾回收器的关系
# Serial收集器
在新生代使用复制算法,在老年代使用标记-清除算法
- 使用单线程进行回收
优点:简单高效,没有线程切换的开销 缺点:无法充分利用多核CPU
# ParNew收集器
使用复制算法,多线程进行回收,可以和CMS收集器配合使用
# Parallel Scavenge收集器
使用复制算法,多线程进行回收
# Serial Old收集器
用于老年代的收集器,使用标记-清除算法
# Parallel Old收集器
# CMS收集器
CMS(Concurrent Mark Sweep)收集器,是一种以获取最短回收停顿时间为目标的收集器. 使用标记-清除算法,分为以下几个阶段
- 初始标记 标记GC Roots能直接关联到的对象(STW)
- 并发标记 标记所有对象
- 重新标记 修正并发标记期间因用户程序继续运行导致标记产生变动的对象(STW)
- 并发清除 清除对象
- 并发清理 清理对象
# G1收集器
G1 (Garbage-First)收集器,最大的特点是可以设置期望停顿时间,然后在这个时间内尽可能多的进行垃圾回收。 不再区分新生代和老年代,而是将内存分为多个区域,每个区域都可以是新生代或者老年代。
region的类型有以下几种:
- Eden 堆内存默认占比 5%
- Survivor 新生代存货区
- Old 老年代区域
- Humongous 超过region50%大小的对象被确认为大对象,会被放到Humongous区域
# 垃圾回收过程
- 初始标记 标记GC Roots能直接关联到的对象(STW)
- 并发标记 标记所有对象
- 最终标记 修正并发标记期间因用户程序继续运行导致标记产生变动的对象(STW)
- 筛选回收 选择回收对象
# G1收集器的优点
- 并行与并发 G1在并行处理的同时,也能与应用程序并发执行,充分利用多核CPU
- 分代收集 G1不再区分新生代和老年代,而是将内存分为多个区域,每个区域都可以是新生代或者老年代
- 空间整合 G1收集器会进行空间整合,减少内存碎片
- 可预测的停顿 G1可以设置期望停顿时间,然后在这个时间内尽可能多的进行垃圾回收
# 垃圾收集分类
- Young GC 并不是Eden区满了马上出发Young GC,而是会去计算Eden去回收大概要多久时间,如果远远小于期望停顿时间,而是增加Eden区的使用,等到下一次Eden区满了,再计算一次,如果大于期望停顿时间,就会触发Young GC。
- Mixed GC 老年代的堆占有率达到设置的值(-XX:InitiatingHeapOccupancyPercent)则触发Mixed GC,回收所有的Young和部分old(根据预期停顿时间)和大对象,一般会先做mixed GC,使用复制算法进行, 把region中的存活对象复制到其他region中,然后清理掉这个region,这样可以减少碎片,如果没有足够的内存存放这些对象则会触发Full GC。
- Full GC 使用单线程进行,系统会停止所有的应用线程,进行垃圾回收,这个过程会比较长,会导致系统停顿。使用标记-清除算法,然后进行空间整理。
# 核心参数
- -XX:+UseG1GC:使用G1收集器
- -XX:MaxGCPauseMillis 设置期望停顿时间
- -XX:G1HeapRegionSize 设置region的大小
- -XX:InitiatingHeapOccupancyPercent 设置老年代的堆占有率达到多少时触发Mixed GC
- -XX:G1MixedGCLiveThresholdPercent 设置Mixed GC后存活对象占比多少时触发Full GC
# ZGC收集器
优点:
- GC时间能控制在10ms范围内
- GC时长只跟GC Roots有关,跟存活对象没有关系
关键技术:
- 着色指针
- 读屏障
# 设计目标
- 停顿时间不超过10ms
- 停顿时间不会随着堆内存的增加而增加
- 支持TB级别的堆内存(8MB~4TB)
# 参考
上次更新: 2024/04/22, 10:37:52