JVM怎样判断一个对象可以被回收

打印 上一主题 下一主题

主题 1715|帖子 1715|积分 5147

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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


  • 可达性分析 (Reachability Analysis)

    • JVM 使用 可达性分析 算法来判断一个对象是否可以被回收。如果从 GC Root(垃圾回收根对象)开始,无法通过任何引用链访问到该对象,则该对象是不可达的,可以被回收。
    • GC Root通常包括以下几种对象:

      • 当火线程的栈帧(局部变量)
      • 方法区中的类和常量池
      • 活泼的线程等


  • 引用范例

    • 强引用:最常见的引用范例。只要对象有强引用,它就不会被回收。
    • 软引用:对象在内存不足时可以被回收。
    • 弱引用:当垃圾回收器进行回收时,弱引用指向的对象会被回收。
    • 虚引用:无法通过虚引用访问到对象,只能用来在对象被回收时收到通知。

举例代码

1. 强引用

  1. public class StrongReferenceExample {
  2.     public static void main(String[] args) {
  3.         Object obj = new Object(); // obj 是对 Object 的强引用
  4.         obj = null;  // 强引用解除,obj 变为 null,但对象还未被回收
  5.     }
  6. }
复制代码
在这个例子中,obj 最初指向一个 Object 实例。如果没有其他引用指向这个对象,那么在 obj = null 后,这个对象成为不可达对象,终极会被垃圾回收器回收。
2. 软引用

  1. import java.lang.ref.SoftReference;
  2. public class SoftReferenceExample {
  3.     public static void main(String[] args) {
  4.         Object obj = new Object();
  5.         SoftReference<Object> softRef = new SoftReference<>(obj);
  6.         obj = null; // 解除强引用
  7.         // 在内存不足时,软引用指向的对象会被回收
  8.         System.gc(); // 请求进行垃圾回收
  9.         Object recoveredObj = softRef.get(); // 获取软引用的对象
  10.         if (recoveredObj != null) {
  11.             System.out.println("软引用指向的对象仍然存在");
  12.         } else {
  13.             System.out.println("软引用指向的对象已经被回收");
  14.         }
  15.     }
  16. }
复制代码
在这个例子中,SoftReference 提供了一种引用范例,当内存紧张时,JVM 会回收软引用指向的对象。
3. 弱引用

  1. import java.lang.ref.WeakReference;
  2. public class WeakReferenceExample {
  3.     public static void main(String[] args) {
  4.         Object obj = new Object();
  5.         WeakReference<Object> weakRef = new WeakReference<>(obj);
  6.         obj = null; // 解除强引用
  7.         // 弱引用对象在下次垃圾回收时会被回收
  8.         System.gc(); // 请求进行垃圾回收
  9.         Object recoveredObj = weakRef.get(); // 获取弱引用的对象
  10.         if (recoveredObj != null) {
  11.             System.out.println("弱引用指向的对象仍然存在");
  12.         } else {
  13.             System.out.println("弱引用指向的对象已经被回收");
  14.         }
  15.     }
  16. }
复制代码
在这个例子中,WeakReference 指向的对象会在下一次垃圾回收时被回收,即使它还有弱引用指向它。
4. 虚引用

虚引用不用于访问对象,它只能和 ReferenceQueue 一起使用,通常用于在对象被回收时实验一些清理工作。
  1. import java.lang.ref.PhantomReference;
  2. import java.lang.ref.ReferenceQueue;
  3. public class PhantomReferenceExample {
  4.     public static void main(String[] args) {
  5.         Object obj = new Object();
  6.         ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
  7.         PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue);
  8.         
  9.         obj = null; // 解除强引用
  10.         System.gc(); // 请求进行垃圾回收
  11.         // 检查虚引用是否已经入队
  12.         if (phantomRef.isEnqueued()) {
  13.             System.out.println("虚引用指向的对象已经被回收");
  14.         } else {
  15.             System.out.println("虚引用指向的对象没有被回收");
  16.         }
  17.     }
  18. }
复制代码
在这个例子中,PhantomReference 是一种特殊的引用范例,允许在对象被回收后通知应用程序实验一些清理工作。
引用计数法和可达性分析法

JVM 常用的垃圾回收算法是 可达性分析法,它查抄对象的引用链。另一种经典的算法是 引用计数法,但这种方法容易出现 循环引用 的标题。
可达性分析法:这是当前大部分 JVM 的实现方式。它从 GC Root 出发,追踪对象图,通过图中的引用关系判断对象是否可达。



  • 如果对象 A 是 GC Root 可达的,且对象 A 引用了对象 B,B 也可达。
  • 如果对象 C 不可达(没有被 GC Root 引用),则对象 C 被认为是垃圾。
引用计数法:这种方法给每个对象添加一个引用计数器,当计数器为 0 时,对象可被回收。但这种方法无法处理处罚循环引用的标题,因此在现实中较少使用。

总结



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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表