Java垃圾回收器

一、前言

垃圾回收(GC)是 Java 区别于 C/C++ 的核心特性之一,它让 JVM 自动管理内存,释放无用对象,大大降低了内存泄漏与野指针的风险。


二、什么是垃圾回收?

简单一句话:JVM 自动识别堆中 "死亡" 的对象,并释放其占用内存的过程。

两个核心问题:

  1. 怎么判断对象已死?
  2. 怎么回收垃圾?

1. 判断对象是否死亡(面试必背)

  • 引用计数法:简单,但无法解决循环引用,Java 不用。
  • 可达性分析算法 :Java 采用。以 GC Root 为起点,能搜索到的对象存活,搜索不到就是垃圾。

GC Root 包括:

  • 虚拟机栈中局部变量 / 方法参数
  • 类静态属性引用
  • 本地方法栈(JNI)引用
  • 活动线程对象

三、垃圾回收的三种基础算法

1. 标记 - 清除

  • 先标记,再清除
  • 缺点:产生大量内存碎片

2. 标记 - 复制

  • 将内存分两半,存活对象复制到另一半,清空原区域
  • 优点:无内存碎片
  • 缺点:浪费空间

3. 标记 - 整理

  • 标记后,让存活对象向一端移动,清理端外内存
  • 优点:无碎片,适合老年代

四、常见垃圾回收器简介

1. Serial / Serial Old

单线程回收,简单高效,适合客户端。

2. ParNew

多线程版本 Serial,多用于新生代,配合 CMS 使用。

3. Parallel Scanvenge / Parallel Old

注重吞吐量,适合后台计算型应用。

4. CMS(Concurrent Mark Sweep)

并发低延迟回收器,以缩短停顿时间为目标。缺点:内存碎片严重、浮动垃圾。

5. G1(Garbage-First)

JDK 9+ 默认回收器,面试绝对重点!

  • 面向服务端
  • 低延迟、可控停顿
  • 无内存碎片
  • 基于 Region 内存布局

五、重点:G1 垃圾回收器 超详细讲解(面试必背)

1. G1 设计思想

G1 不再将堆分为连续的新生代、老年代,而是将堆划分为许多大小相同的 Region。每个 Region 可以是:Eden、Survivor、Old、Humongous(存超大对象)。

G1 的核心目标:指定的停顿时间内 ,回收价值最大的垃圾。

2. G1 最重要:完整回收四阶段

① 初始标记(Initial Mark)

  • STW(Stop The World)
  • 只标记 GC Roots 直接关联 的对象
  • 速度极快

② 并发标记(Concurrent Mark)

  • 与用户线程并发执行
  • 对整个堆进行可达性分析,标记所有存活对象
  • 耗时较长,但不影响业务运行

③ 最终标记(Final Mark)

  • STW
  • 修正并发标记阶段因程序运行产生的变动
  • 速度快

④ 筛选回收(Evacuation)------ G1 最核心

  • STW
  • 对所有 Region 按回收价值和成本排序
  • 根据用户设置的 最大停顿时间(MaxGCPauseMillis) 选择要回收的 Region
  • 使用复制算法,将存活对象复制到空 Region,清空原 Region
  • 无内存碎片

3. G1 全过程一句话总结

G1 回收分为四步:初始标记(STW)→ 并发标记 → 最终标记(STW)→ 筛选回收(STW)。通过可控停顿、优先回收高价值 Region,实现低延迟、无碎片、高稳定。

4. G1 核心特点(面试必问)

  1. 基于 Region 分代,内存不连续
  2. 可预测停顿时间 ,由 -XX:MaxGCPauseMillis 控制
  3. 优先回收垃圾最多的区域(Garbage-First)
  4. 复制算法,无内存碎片
  5. 筛选回收阶段 STW,但只回收部分 Region,速度极快
  6. 支持大对象直接存入 Humongous Region

六、G1 vs CMS(高频对比)

  • CMS:标记 - 清除,有碎片,停顿不可控
  • G1:标记 - 复制,无碎片,停顿可精准控制
  • G1 整体更稳定,是现代服务端首选

七、总结

Java 垃圾回收是 JVM 自动管理内存的核心机制,通过可达性分析 判断对象是否死亡,使用标记 - 清除、标记 - 复制、标记 - 整理三种基础算法。常见回收器中,G1 是目前最主流、面试最重要的回收器。

G1 基于 Region 内存布局,追求可控停顿、最大回收价值 ,回收过程分为:初始标记、并发标记、最终标记、筛选回收四步。它无内存碎片、停顿可预测,是生产环境与面试中的绝对核心。

相关推荐
wuqingshun3141593 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
我真会写代码6 小时前
深入理解JVM GC:触发机制、OOM关联及核心垃圾回收算法
java·jvm·架构
森林里的程序猿猿7 小时前
垃圾收集器G1和ZGC
java·jvm·算法
Aawy1209 小时前
Python生成器(Generator)与Yield关键字:惰性求值之美
jvm·数据库·python
爱丽_10 小时前
GC 怎么判定“该回收谁”:GC Roots、可达性分析、四种引用与回收算法
java·jvm·算法
小钟不想敲代码10 小时前
JVM入门
jvm
柒.梧.10 小时前
线上问题定位+JVM核心面试题全解析
jvm
爱丽_12 小时前
JVM 堆参数怎么设:先建立内存基线,再谈性能优化
java·jvm·性能优化
qq_3349031512 小时前
使用Flask快速搭建轻量级Web应用
jvm·数据库·python