当前位置: 首页 > article >正文

JVM如何判断一个对象可以被回收

在 Java 中,JVM 使用 垃圾回收器 (GC) 来自动管理内存。JVM 判断一个对象是否可以被回收的主要依据是 对象是否可达。具体来说,如果某个对象不再被任何可达的引用所引用,那么这个对象就可以被认为是 垃圾,可以被回收。

判断一个对象是否可以被回收的标准:

  1. 可达性分析 (Reachability Analysis)
    • JVM 使用 可达性分析 算法来判断一个对象是否可以被回收。如果从 GC Root(垃圾回收根对象)开始,无法通过任何引用链访问到该对象,则该对象是不可达的,可以被回收。
    • GC Root通常包括以下几种对象:
      • 当前线程的栈帧(局部变量)
      • 方法区中的类和常量池
      • 活跃的线程等
  2. 引用类型
    • 强引用:最常见的引用类型。只要对象有强引用,它就不会被回收。
    • 软引用:对象在内存不足时可以被回收。
    • 弱引用:当垃圾回收器进行回收时,弱引用指向的对象会被回收。
    • 虚引用:无法通过虚引用访问到对象,只能用来在对象被回收时收到通知。

举例代码

1. 强引用
public class StrongReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object(); // obj 是对 Object 的强引用
        obj = null;  // 强引用解除,obj 变为 null,但对象还未被回收
    }
}

在这个例子中,obj 最初指向一个 Object 实例。如果没有其他引用指向这个对象,那么在 obj = null 后,这个对象成为不可达对象,最终会被垃圾回收器回收。

2. 软引用
import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        SoftReference<Object> softRef = new SoftReference<>(obj);
        obj = null; // 解除强引用

        // 在内存不足时,软引用指向的对象会被回收
        System.gc(); // 请求进行垃圾回收

        Object recoveredObj = softRef.get(); // 获取软引用的对象
        if (recoveredObj != null) {
            System.out.println("软引用指向的对象仍然存在");
        } else {
            System.out.println("软引用指向的对象已经被回收");
        }
    }
}

在这个例子中,SoftReference 提供了一种引用类型,当内存紧张时,JVM 会回收软引用指向的对象。

3. 弱引用
import java.lang.ref.WeakReference;

public class WeakReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        WeakReference<Object> weakRef = new WeakReference<>(obj);
        obj = null; // 解除强引用

        // 弱引用对象在下次垃圾回收时会被回收
        System.gc(); // 请求进行垃圾回收

        Object recoveredObj = weakRef.get(); // 获取弱引用的对象
        if (recoveredObj != null) {
            System.out.println("弱引用指向的对象仍然存在");
        } else {
            System.out.println("弱引用指向的对象已经被回收");
        }
    }
}

在这个例子中,WeakReference 指向的对象会在下一次垃圾回收时被回收,即使它还有弱引用指向它。

4. 虚引用

虚引用不用于访问对象,它只能和 ReferenceQueue 一起使用,通常用于在对象被回收时执行一些清理工作。

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue);
        
        obj = null; // 解除强引用

        System.gc(); // 请求进行垃圾回收

        // 检查虚引用是否已经入队
        if (phantomRef.isEnqueued()) {
            System.out.println("虚引用指向的对象已经被回收");
        } else {
            System.out.println("虚引用指向的对象没有被回收");
        }
    }
}

在这个例子中,PhantomReference 是一种特殊的引用类型,允许在对象被回收后通知应用程序执行一些清理工作。

引用计数法和可达性分析法

JVM 常用的垃圾回收算法是 可达性分析法,它检查对象的引用链。另一种经典的算法是 引用计数法,但这种方法容易出现 循环引用 的问题。

可达性分析法:这是当前大部分 JVM 的实现方式。它从 GC Root 出发,追踪对象图,通过图中的引用关系判断对象是否可达。
  • 如果对象 A 是 GC Root 可达的,且对象 A 引用了对象 B,B 也可达。
  • 如果对象 C 不可达(没有被 GC Root 引用),则对象 C 被认为是垃圾。
引用计数法:这种方法给每个对象添加一个引用计数器,当计数器为 0 时,对象可被回收。但这种方法无法处理循环引用的问题,因此在实际中较少使用。

总结

  • JVM 判断对象是否可以回收,主要基于 可达性分析法,如果一个对象不可达(即没有任何引用链可以访问到该对象),它就可以被回收。
  • 引用类型(强引用、软引用、弱引用、虚引用)会影响对象的回收行为。

http://www.kler.cn/a/612345.html

相关文章:

  • 【Python】multiprocessing - 进程隔离
  • 高级数据结构04动态规划
  • Quarkus云原生服务开发详解
  • 《向量数据库指南》——解密DeepSearcher:推动AI智能报告生成的新范式
  • leetcode543.二叉树的直径
  • HarmonyOS-ArkUI Grip组件
  • QTcpSocket(客户端实现)多线程连接慢问题
  • MyBatis-Plus(Ⅲ)IService详解
  • python蓝桥杯刷题的重难点知识笔记
  • 【RHCE】LVS-NAT模式负载均衡实验
  • Flask接口开发--POST接口
  • 数据仓库 - 转转 - 一面凉经
  • 算力盒子VS边缘计算盒子
  • 脉冲编码器:精准定位与高效控制的科技先锋
  • 创建login.api.js步骤和方法
  • 【蓝桥杯】重点冲刺
  • ubuntu24.04.2 NVIDIA GeForce RTX 4060笔记本安装驱动
  • Milvus 与 Spring Boot 集成
  • SpringMVC 拦截器详解与实战
  • GAUSSDB 分布式存储机制深度解析