目录

深入理解-Java-虚拟机之垃圾收集

深入理解 Java 虚拟机之垃圾收集

https://i-blog.csdnimg.cn/direct/a95cb98cf4684b9f964080e1ff1e16df.png#pic_center

垃圾收集(Garbage Collection,GC)是 Java 虚拟机(JVM)内存管理的核心机制,主要针对 Java 堆方法区 进行回收。线程私有的程序计数器、虚拟机栈和本地方法栈随线程生命周期结束而自然消失,无需 GC。本文将详细探讨 GC 的判定依据、算法、收集器及内存分配策略。


  • 原理 :对象维护一个引用计数器,被引用时加 1,引用失效时减 1,计数为 0 时可回收。
  • 缺陷 :无法解决循环引用问题,例如两个对象互相引用,计数永不为 0。
  • 结论 :JVM 不采用此算法。
  • 原理 :从 GC Roots 开始搜索,可达对象存活,不可达对象死亡。
  • GC Roots
    • 虚拟机栈中的引用对象。
    • 本地方法栈中的引用对象。
    • 方法区中的静态属性和常量引用对象。
  • 应用 :JVM 主流采用此算法。

Java 提供四种引用类型,影响对象回收:

  • 强引用new 创建的对象,不会回收。
  • 软引用SoftReference ,内存不足时回收。
  • 弱引用WeakReference ,下次 GC 时回收,常用于缓存(如 WeakHashMap )。
  • 虚引用PhantomReference ,仅用于接收回收通知。
  • 目标 :废弃常量和无用类。
  • 类卸载条件
    1. 所有实例已回收。
    2. 类加载器已回收。
    3. Class 对象未被引用。
  • 控制 :通过 -Xnoclassgc 参数决定是否卸载。
  • 作用 :对象回收前可执行的自救方法。
  • 问题 :运行代价高、不确定性大,建议避免使用。

  • 停顿时间 :GC 导致的程序暂停时长。
  • 吞吐量 :用户代码运行时间占比。
  • 过程 :标记需回收对象,然后清除。
  • 缺点 :效率低,产生内存碎片。
  • 过程 :标记后将存活对象移至一端,清理边界外内存。
  • 优点 :解决碎片问题。
  • 缺点 :整理开销大。
  • 过程 :内存分两块,存活对象复制到空闲块,清理已用块。
  • 优点 :无碎片。
  • 缺点 :内存利用率低(改进为 Eden + 2 Survivor)。
  • 原理 :根据对象生命周期分代,年轻代用复制算法,老年代用标记-清除或标记-整理。
  • 堆结构
    • 新生代 :Eden + 2 Survivor,默认比例 8:1:1。
    • 老年代 :存放长生命周期对象。
    • 永久代 :JDK 8 前的方法区实现,现为元空间。

HotSpot 提供多种垃圾收集器,各有适用场景:

  • 特点 :单线程,Stop-The-World,适用于 Client 模式。
  • 组合
    • Serial :年轻代,复制算法, -XX:+UseSerialGC
    • Serial Old :老年代,标记-整理。
  • 目标 :高吞吐量,Server 模式默认。
  • 组合
    • Parallel Scavenge :年轻代,复制算法, -XX:+UseParallelGC
    • Parallel Old :老年代,标记-整理, -XX:+UseParallelOldGC
  • 参数
    • -XX:MaxGCPauseMillis :控制停顿时间。
    • -XX:GCTimeRatio :设置吞吐量。
    • -XX:+UseAdaptiveSizePolicy :自适应调整。
  • 目标 :最短停顿时间。
  • 组合-XX:+UseConcMarkSweepGC ,ParNew(年轻代)+ CMS(老年代)+ Serial Old(备用)。
  • 步骤
    1. 初始标记(停顿)。
    2. 并发标记。
    3. 重新标记(停顿)。
    4. 并发清除。
  • 缺点 :内存碎片、浮动垃圾,需预留空间。
  • 特点 :兼顾吞吐量和停顿时间,JDK 9+ 默认, -XX:+UseG1GC
  • 分区 :堆划分为多个 Region,动态分配角色。
  • 步骤
    1. 初始标记。
    2. 并发标记。
    3. 最终标记。
    4. 筛选回收(优先高价值 Region)。
  • 优点 :无碎片,可预测停顿。
收集器类型算法目标场景
Serial串行年轻代复制低停顿单核 Client 模式
Serial Old串行老年代标记-整理低停顿CMS 备用
ParNew并行年轻代复制低停顿与 CMS 配合
Parallel Scavenge并行年轻代复制高吞吐量后台运算
Parallel Old并行老年代标记-整理高吞吐量后台运算
CMS并发老年代标记-清除低停顿Web 服务端
G1并发全部标记-整理+复制低停顿+吞吐量服务端应用

  • 触发 :Eden 区满。
  • 过程 :存活对象复制到 Survivor,年龄达阈值(默认 15, -XX:MaxTenuringThreshold )晋升老年代。
  • 触发条件
    1. System.gc() (建议性,可禁用)。
    2. 老年代空间不足。
    3. 方法区(元空间)不足。
    4. Minor GC 晋升平均大小超老年代剩余空间。
    5. 对象大于 Survivor 和老年代可用空间。
  • Eden 优先 :新对象分配在 Eden。
  • 大对象直入老年代-XX:PretenureSizeThreshold
  • 长期存活晋升 :年龄超阈值。
  • 动态年龄判定 :Survivor 半满时提前晋升。
  • 空间担保 :老年代为 Minor GC 提供担保。

JVM 的垃圾收集机制通过可达性分析、分代收集和多样化的收集器,高效管理内存。串行适合小型应用,并行追求吞吐量,CMS 和 G1 优化停顿时间。理解 GC 原理和策略,有助于调优程序性能,避免内存溢出等问题。