JVM垃圾回收机制(上):GC算法与内存管理

图片[1]-JVM垃圾回收机制(上):GC算法与内存管理-速优课

垃圾回收(GC)是 JVM 自动内存管理的核心机制,它自动回收不再使用的对象,避免内存泄漏。本文将深入探讨垃圾回收的基本原理、常用算法以及内存管理策略。

一、垃圾回收的基本概念

什么是垃圾

垃圾是指不再被任何引用指向的对象。这些对象占用的内存可以被回收,供新对象使用。

垃圾回收的目标

  1. 回收无用对象:释放不再使用的内存
  2. 减少内存碎片:整理内存空间,提高内存利用率
  3. 保证程序运行:避免内存溢出(OutOfMemoryError)

垃圾回收的挑战

  1. 如何判定对象是否存活:需要高效的可达性分析算法
  2. 如何高效回收内存:需要选择合适的回收算法
  3. 如何减少停顿时间:避免影响应用程序的响应性

二、对象存活判定算法

引用计数法

原理:为每个对象维护一个引用计数器,当引用增加时计数加 1,引用减少时计数减 1,计数为 0 时对象可回收。

优点:简单、高效

缺点:无法处理循环引用

// 循环引用示例
class Node {
    Node next;
}
​
Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a;
a = null;
b = null;
// 此时 a 和 b 的引用计数都不为 0,但它们都是垃圾

可达性分析法

原理:从 GC Roots 出发,遍历所有可达对象,不可达对象即为垃圾。

GC Roots 的种类

类型说明
虚拟机栈引用的对象局部变量表中的引用
方法区中类静态属性引用的对象静态变量
方法区中常量引用的对象常量池中引用
本地方法栈引用的对象native 方法中的引用

可达性分析过程

GC Roots
    ↓
  对象A ← 对象B ← 对象C
                  ↓
               对象D(不可达,可回收)

Java 中的引用类型

Java 提供了四种引用类型,用于控制对象的生命周期:

引用类型说明垃圾回收时机
强引用默认引用类型永远不会被回收
软引用内存不足时回收抛出 OOM 前
弱引用下次 GC 时回收每次 GC
虚引用唯一目的是接收回收通知随时回收
// 引用类型示例
String str = new String("hello"); // 强引用
​
SoftReference<String> softRef = new SoftReference<>(new String("soft"));
WeakReference<String> weakRef = new WeakReference<>(new String("weak"));
PhantomReference<String> phantomRef = new PhantomReference<>(
    new String("phantom"), new ReferenceQueue<>());

三、垃圾回收算法

标记-清除算法

流程

  1. 标记:遍历所有可达对象,标记为存活
  2. 清除:遍历堆内存,回收未标记的对象

优点:简单

缺点

  • 产生内存碎片
  • 效率较低(需要两次遍历)

标记-复制算法

流程

  1. 将堆内存分为两个相等的区域(From 区和 To 区)
  2. 只使用 From 区分配对象
  3. 垃圾回收时,将存活对象复制到 To 区
  4. 清空 From 区,交换两个区域的角色

优点

  • 无内存碎片
  • 分配效率高(指针碰撞)

缺点

  • 内存利用率低(只有一半可用)
  • 复制开销大

标记-整理算法

流程

  1. 标记:遍历所有可达对象,标记为存活
  2. 整理:将存活对象向一端移动,然后清除边界外的内存

优点

  • 无内存碎片
  • 内存利用率高

缺点:整理开销大

分代收集算法

结合以上三种算法,根据对象的生命周期分为不同代:

特点回收算法
新生代对象生命周期短,大量创建和回收标记-复制
老年代对象生命周期长,存活时间久标记-清除/标记-整理
永久代/元空间存储类元数据、常量池标记-清除

四、垃圾回收器

串行回收器(Serial)

  • 单线程回收:使用一条线程进行垃圾回收
  • 适用于:客户端应用、单核 CPU
  • 优点:简单、高效(无线程切换开销)
  • 缺点:停顿时间长

并行回收器(Parallel)

  • 多线程回收:使用多条线程进行垃圾回收
  • 适用于:服务器端应用、多核 CPU
  • 优点:回收速度快
  • 缺点:停顿时间较长

CMS 回收器(Concurrent Mark Sweep)

  • 并发回收:与应用线程并发执行
  • 适用于:对响应时间要求高的应用
  • 优点:停顿时间短
  • 缺点
    • 内存碎片问题
    • CPU 占用高
    • 无法处理浮动垃圾

G1 回收器(Garbage First)

  • 分区回收:将堆内存分为多个 Region
  • 并发回收:与应用线程并发执行
  • 可预测停顿:可以设置最大停顿时间
  • 适用于:大堆内存(4GB+)
  • 优点
    • 停顿时间可控
    • 无内存碎片
    • 效率高

ZGC 回收器(Z Garbage Collector)

  • 低延迟回收:停顿时间不超过 10ms
  • 适用于:超大堆内存(16GB+)
  • 优点:极低延迟
  • 缺点:吞吐量略低

五、垃圾回收的触发条件

新生代回收(Minor GC)

触发条件:

  • Eden 区满时
  • 新对象分配失败时

特点:

  • 频率高
  • 停顿时间短

老年代回收(Major GC/Full GC)

触发条件:

  • 老年代空间不足时
  • 永久代/元空间不足时
  • 调用 System.gc() 时

特点:

  • 频率低
  • 停顿时间长

六、总结

垃圾回收是 JVM 的核心功能,涉及多个方面:

  1. 存活判定:引用计数法和可达性分析法
  2. 回收算法:标记-清除、标记-复制、标记-整理
  3. 分代收集:新生代使用复制算法,老年代使用清除/整理算法
  4. 垃圾回收器:Serial、Parallel、CMS、G1、ZGC
  5. 触发条件:Minor GC(Eden 区满)、Major GC(老年代满)

理解垃圾回收机制,对于编写高效代码和进行 JVM 调优至关重要。

© 版权声明
THE END
喜欢就支持一下吧
点赞6
相关推荐
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容

温馨提示:
1、本内容转载于网络,版权归原作者所有!
2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!