JVM垃圾回收机制面试笔记

发布于:2025-07-14 ⋅ 阅读:(22) ⋅ 点赞:(0)

1. 垃圾回收的基本概念

什么是垃圾?

当一个或多个对象没有任何引用指向它们时,这些对象就成为了垃圾,可能会被垃圾回收器回收。

垃圾识别算法

  • 引用计数法:对象被引用时计数+1,引用失效时计数-1,计数为0时可回收。存在循环引用问题,现在基本不用。
  • 可达性分析算法:从GC Roots开始,通过引用链判断对象是否可达。不可达的对象可被回收。这是主流的垃圾识别算法。

GC Roots包括:虚拟机栈中的引用、方法区中的静态变量和常量、本地方法栈中的引用、活跃线程等。

2. 垃圾回收算法

标记-清除算法(Mark-Sweep)

  • 过程:标记所有需要回收的对象,然后清除这些对象
  • 优点:标记和清除速度较快,不需要移动对象
  • 缺点:产生内存碎片,影响大对象分配
    标记-清除算法

标记-整理算法(Mark-Compact)

  • 过程:标记后将存活对象向内存一端移动,清理掉边界外的内存
  • 优点:解决了内存碎片问题
  • 缺点:需要移动对象,效率相对较低
    标记-整理算法

复制算法(Copying)

  • 过程:将内存分为两块,每次只使用一块,回收时将存活对象复制到另一块
  • 优点:回收效率高,无内存碎片
  • 缺点:内存利用率只有50%
    复制算法

分代收集算法

不同代使用不同算法:新生代使用复制算法,老年代使用标记-清除或标记-整理算法。

3. JVM内存分代模型

堆内存划分

  • 新生代:老年代 = 1:2
  • 新生代内部:Eden:Survivor0:Survivor1 = 8:1:1
    堆内存划分

对象分配和晋升过程

  1. 新对象优先分配到Eden区
  2. Eden区满时触发Minor GC,存活对象复制到Survivor区
  3. Survivor区中对象每经历一次GC,年龄+1
  4. 年龄达到15(默认)或Survivor区空间不足时,对象晋升到老年代
  5. 大对象(超过Eden区一半)直接进入老年代

4. GC类型详解

Minor GC(Young GC)

  • 触发条件:Eden区空间不足
  • 回收范围:新生代
  • 特点:频率高,耗时短

Major GC

  • 触发条件:老年代空间不足
  • 回收范围:老年代
  • 特点:频率低,耗时长

Full GC

  • 触发条件:整个堆空间不足、方法区空间不足、System.gc()调用等
  • 回收范围:整个堆 + 方法区
  • 特点:耗时最长,应尽量避免

Mixed GC

  • 回收范围:新生代 + 老年代部分区域
  • 特点:G1收集器特有

5. 垃圾收集器对比

串行收集器(Serial/SerialOld)

  • 特点:单线程收集,STW时间长
  • 适用场景:单核CPU、小内存应用
  • 算法:新生代使用复制算法,老年代使用标记-整理算法
    串行收集器

并行收集器(ParallelNew/ParallelOld)

  • 特点:多线程收集,JDK8默认收集器
  • 适用场景:多核CPU、注重吞吐量的应用
  • 算法:新生代使用复制算法,老年代使用标记-整理算法
    并行收集器

CMS收集器(Concurrent Mark Sweep)

  • 特点:并发收集,低延迟,使用标记-清除算法
  • 适用场景:注重响应时间的应用
  • 缺点:产生内存碎片,可能发生并发失败
    CMS收集器

G1收集器(Garbage First)

  • 特点:JDK9+默认收集器,兼顾吞吐量和延迟
  • 内存模型:将堆划分为多个Region,每个Region可以是Eden、Survivor、Old、Humongous
  • 回收过程:新生代回收 → 并发标记 → 混合收集
  • 优点:可预测的停顿时间,适合大内存应用

6. 引用类型详解

强引用(Strong Reference)

  • 特点:最常见的引用类型,如 Object obj = new Object()
  • 回收条件:只有当GC Roots不可达时才会被回收
  • 使用场景:一般对象引用
    强引用

软引用(Soft Reference)

  • 特点:内存不足时会被回收
  • 回收条件:在内存不足时,即使有软引用指向,也会被回收
  • 使用场景:内存敏感的缓存
    软引用

弱引用(Weak Reference)

  • 特点:下次GC时必定被回收
  • 回收条件:只要发生GC,无论内存是否充足都会被回收
  • 使用场景:ThreadLocal防止内存泄漏
    弱引用

虚引用(Phantom Reference)

  • 特点:最弱的引用类型,无法通过虚引用获取对象
  • 使用场景:配合引用队列使用,监控对象回收,管理直接内存
    虚引用

7. 面试高频问题

如何判断对象可以被回收?

通过可达性分析算法,从GC Roots开始遍历引用链,不可达的对象可以被回收。

什么情况下会发生Full GC?

  • 老年代空间不足
  • 方法区空间不足
  • 通过Minor GC后进入老年代的对象大小超过老年代可用内存
  • 手动调用System.gc()

如何优化GC性能?

  • 合理设置堆内存大小
  • 选择合适的垃圾收集器
  • 优化代码,减少不必要的对象创建
  • 避免内存泄漏
  • 调整新生代和老年代的比例

G1收集器的优势?

  • 低延迟:可预测的停顿时间
  • 高吞吐量:并发收集,减少STW时间
  • 内存整理:避免内存碎片
  • 适合大内存:Region化管理,适合大堆应用

8. 调优建议

常用JVM参数

  • -Xms:初始堆大小
  • -Xmx:最大堆大小
  • -Xmn:新生代大小
  • -XX:SurvivorRatio:Eden和Survivor比例
  • -XX:MaxTenuringThreshold:对象晋升老年代的年龄阈值
  • -XX:+UseG1GC:使用G1收集器

监控工具

  • JConsole:JVM自带的监控工具
  • VisualVM:可视化监控工具
  • JProfiler:商业性能分析工具
  • GC日志分析:通过-XX:+PrintGCDetails开启详细GC日志

网站公告

今日签到

点亮在社区的每一天
去签到