java的垃圾回收器和内存回收策略

阅读 16

06-01 09:00

Java的垃圾回收(GC)机制是JVM自动管理内存的核心,通过回收不再使用的对象释放堆内存,避免内存泄漏。其核心包括垃圾回收器和内存回收策略,以下从原理、算法、回收器类型及优化策略展开说明:

⚙️ 一、垃圾回收基本原理

  1. 对象存活判定
  • 可达性分析算法:从GC Root(如虚拟机栈局部变量、静态属性、常量等)出发,遍历引用链。未被引用的对象标记为“不可达”,即垃圾。
  • 引用类型
  • 强引用:普遍存在,只要存在则不会被回收。
  • 软引用:内存不足时回收(适用于缓存)。
  • 弱引用:下次GC时必回收。
  • 虚引用:仅用于回收通知。
  1. 方法区回收
    主要回收废弃常量(如未被引用的字符串)和无用类(需满足:实例全回收、类加载器已回收、Class对象未被引用)。

🔄 二、垃圾回收算法

  1. 标记-清除(Mark-Sweep)
  • 步骤:标记所有可达对象 → 清除未标记对象。
  • 缺点:内存碎片化,影响大对象分配效率。
  1. 复制算法(Copying)
  • 步骤:将内存分为两块,存活对象复制到另一块 → 清空原区域。
  • 应用:新生代(Eden区 + 两个Survivor区,默认8:1:1),Minor GC后存活对象移至Survivor。
  • 缺点:空间利用率仅50%。
  1. 标记-整理(Mark-Compact)
  • 步骤:标记可达对象 → 向内存一端移动 → 清理边界外空间。
  • 应用:老年代,避免碎片化。
  1. 分代收集(Generational Collection)
  • 新生代:对象存活率低,采用复制算法(Minor GC)。
  • 老年代:对象存活率高,采用标记-清除或标记-整理(Major GC/Full GC)。

🛠️ 三、主流垃圾回收器及工作原理

回收器

特点

适用场景

Serial GC

单线程执行GC,全程STW(Stop-The-World)

客户端/小内存应用

Parallel GC

多线程并行回收,提高吞吐量(-XX:+UseParallelGC)

后台计算型应用(高吞吐需求)

CMS GC

并发标记清除,减少STW时间(分4阶段:初始标记→并发标记→重新标记→并发清除)

低延迟Web服务

G1 GC

分区堆(Region),优先回收垃圾最多区域;可预测停顿模型

大内存、高响应应用(JDK9+默认)

ZGC/Shenandoah

TB级堆内存支持,停顿时间<10ms,全程并发

超低延迟场景(如金融交易)

  • STW(Stop-The-World):GC时暂停所有应用线程。
  • 并发 vs 并行:并发指GC与应用线程交替执行;并行指多线程同时GC。

📊 四、内存分配与回收策略

  1. 对象分配原则
  • 新生代Eden分配:多数对象在Eden区创建,空间不足时触发Minor GC。
  • 大对象直入老年代:避免在Eden区频繁复制(如长数组)。
  • 长期存活进老年代:对象年龄计数器达阈值(默认15)后晋升。
  1. GC触发条件
  • Minor GC:Eden区满时触发。
  • Full GC:老年代空间不足、方法区不足、或主动调用System.gc()

⚡ 五、优化建议

  1. 垃圾回收器选择
  • 吞吐优先 → Parallel GC;
  • 低延迟 → G1/ZGC;
  • 小堆 → Serial GC。
  1. 关键参数调优
  • 堆大小:-Xms(初始堆)、-Xmx(最大堆);
  • 新生代比例:-XX:NewRatio(老年代/新生代比例);
  • Surviv区调整:-XX:SurvivorRatio(Eden/Survivor)。
  1. 监控工具
  • JVisualVM/GC日志分析:监控GC频率、停顿时间、内存泄漏(如对象持续进入老年代)。

💎 总结

Java垃圾回收通过分代模型多样化回收器平衡吞吐、延迟与内存开销。理解不同回收器特性(如G1的分区回收、ZGC的并发压缩)及内存分配策略(如大对象直进老年代),结合监控调优,可显著提升应用性能。实际部署需根据应用场景(如高并发/大数据量)选择合适组合,避免频繁Full GC导致的系统卡顿。

精彩评论(0)

0 0 举报