对象回收判断与GC算法深度解析

一、对象回收判断依据

1. 可达性分析算法(主流JVM采用)

判定标准

  • GC Roots作为起点,向下搜索引用链

  • 不在任何引用链上的对象判定为可回收

GC Roots包括

1. 虚拟机栈中引用的对象(局部变量)
2. 方法区中类静态属性引用的对象
3. 方法区中常量引用的对象
4. 本地方法栈中JNI引用的Native对象
5. Java虚拟机内部引用(Class对象、异常对象等)

2. 引用计数法(Python等使用)

实现原理

class Object {
    int refCount = 0;  // 引用计数器
    void addRef() { refCount++; }
    void release() { if(--refCount == 0) delete this; }
}

缺陷

  • 无法解决循环引用问题(如A引用B,B引用A)

二、主流GC算法分类

1. 标记-清除(Mark-Sweep)

执行过程

  1. 标记所有可达对象

  2. 清除未标记对象
    特点

  • 产生内存碎片

  • 适用于老年代(CMS收集器部分阶段使用)

2. 标记-复制(Mark-Copy)

内存布局

Eden区(80%) + Survivor0(10%) + Survivor1(10%)

执行过程

  1. 将Eden和Survivor0存活对象复制到Survivor1

  2. 清空Eden和Survivor0
    特点

  • 无内存碎片

  • 空间利用率仅90%

  • 适用于新生代(ParNew等收集器)

3. 标记-整理(Mark-Compact)

执行过程

  1. 标记存活对象

  2. 将存活对象向一端移动

  3. 清理边界外内存
    特点

  • 无内存碎片

  • 移动对象开销大

  • 适用于老年代(Serial Old等收集器)

4. 分代收集(Generational)

组合策略

  • 新生代:标记-复制

  • 老年代:标记-清除/标记-整理
    理论依据

  • 弱分代假说(绝大多数对象朝生夕死)

  • 强分代假说(熬过多次GC的对象难以消亡)

三、现代JVM主流GC算法

1. HotSpot虚拟机默认选择

JDK版本新生代老年代
JDK7/8Parallel ScavengeParallel Old
JDK9+G1(全区域统一处理)
JDK17ZGC(实验特性)

2. G1收集器(Garbage-First)

核心创新

  • 将堆划分为多个Region(默认2048个)

  • 优先回收价值最大(垃圾最多)的Region

  • 可预测的停顿时间模型(-XX:MaxGCPauseMillis)

执行流程

  1. 初始标记(STW)

  2. 并发标记

  3. 最终标记(STW)

  4. 筛选回收(Evacuation)

四、深度问题解析

Q1:如何手动触发GC?System.gc()一定有效吗?

关键点

  • System.gc()只是建议而非强制

  • 添加-XX:+DisableExplicitGC参数会忽略调用

  • 更可靠方式:

    // 通过内存分配施压
    byte[] pressure = new byte[1024*1024*1024];
  • 推荐使用JMX触发诊断性GC:

    jcmd <pid> GC.run

Q2:如何判断对象是否被回收?

实践方法

  1. finalize()方法(不推荐):

    protected void finalize() throws Throwable {
        System.out.println("对象即将被回收");
    }
  2. 引用队列监控

    ReferenceQueue<Object> queue = new ReferenceQueue<>();
    WeakReference<Object> ref = new WeakReference<>(new Object(), queue);
    // 监控queue.poll()获取被回收的引用
  3. JVMTI工具

    JNIEXPORT void JNICALL
    callback_object_free(jvmtiEnv *jvmti, jlong tag) {
        printf("Object freed: %lld\n", tag);
    }

Q3:为什么G1取代CMS成为默认收集器?

技术演进原因

  1. 内存碎片问题

    • CMS使用标记-清除,长期运行后触发Full GC

    • G1通过压缩避免碎片(类似标记-整理)

  2. 停顿时间控制

    • CMS难以预测停顿时间

    • G1可设置最大停顿目标(默认200ms)

  3. 大内存适配

    • CMS在堆>4GB时性能下降明显

    • G1可有效管理数十GB堆内存

  4. 算法统一

    • G1不再严格分代,适合现代应用内存特征

五、GC算法选择建议

场景推荐收集器参数配置示例
小型应用(<4GB)Parallel Scavenge-XX:+UseParallelGC
低延迟要求G1-XX:+UseG1GC -XX:MaxGCPauseMillis=100
超大堆(>32GB)ZGC-XX:+UseZGC -Xmx64g
云原生环境Shenandoah-XX:+UseShenandoahGC

理解GC算法有助于:

  • 合理配置JVM参数

  • 优化应用内存使用

  • 诊断性能问题

  • 展示系统级调优能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值