zoukankan      html  css  js  c++  java
  • 谁才是真正的垃圾:判断对象的可触及性

    垃圾回收的基本思想是考察每一个对象的可触及性,即从根节点开始是否可以访问到这个对象,如果可以,则说明当前对象正在被使用,如果从所有的根节点都无法访问到某个对象,说明该对象已经不再使用了,一般来说,此对象符合垃圾回收的条件。但是,一个无法触及的对象有可能在某个条件下复活自己,如果这样,那么对它的回收就是不合理的,为此,需要给出一个可触及性状态的定义,并规定在什么状态下,才可以安全的回收对象。

    可触及的包括3种状态:

    • 可触及的:从根节点开始,可以到达这个对象;
    • 可复活的:对象的所有引用都被释放,但是对象有可能在finalize()函数中复活;
    • 不可触及的:对象的finalize()函数被调用,并且没有复活,那么就会进入不可触及状态,不可触及的对象不可能被复活,因为finalize()函数只会被调用一次。

    以上3种状态,只有在对象不可触及时才可以被回收。

    1 对象的复活

    实例1 :前面提到,对象可能在finalize()函数中复活自己,这里给出一个实例。

    package com.jvm;
    public class CanReliveObj {
      public static CanReliveObj obj ;
      @Override
      protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("CanReliveObj finalize called");
        obj = this;
      }
      @Override
      public String toString() {
        return "CanReliveObj";
      }

      public static void main(String[] args) throws InterruptedException {
        obj = new CanReliveObj();
        obj = null;
        System.gc();
        Thread.sleep(1000);
        if(obj==null){
          System.out.println("obj is null");
        }else{
          System.out.println("obj 可用");
        }
        System.out.println("第二次GC");
        obj = null;
        System.gc();
        Thread.sleep(1000);
        if(obj==null){
          System.out.println("obj is null");
        }else{
          System.out.println("obj 可用");
        }
      }
    }

    运行代码打印:

    CanReliveObj finalize called
    obj 可用
    第二次GC
    obj is null

    可以看出,在第一次将obj置为null后,进行GC,结果发现obj对象被复活了。等到第二次再释放对象引用并运行GC,对象才真正被回收。这是因为第一次GC时,在finalize()函数调用之前,虽然系统中的引用已经被清除,但是在实例方法finalize()中,对象的引用this依然被传入方法内部,导致引用外泄,对象复活,此时对象又变成可触及状态。由于finalize()函数只会被调用一次,因此,在第二次清除释放对象的引用时,对象就再无机会复活,因此会被回收。

    注意:

    finalize()函数是一个糟糕的应用模式,不推荐使用finalize()函数释放资源。

    因为:其一,finalize()函数有可能发生引用外泄,在无意间复活对象

            其二,由于finalize()是被系统调用的,调用时间是不明确的,因此不是一个好的资源释放方案,推荐使用try-catch-finally语句进行资源的释放。

  • 相关阅读:
    RabbitMQ 路由选择 (Routing)
    RabbitMQ 发布/订阅
    RabbitMQ 工作队列
    MySQL中的insert ignore into, replace into等的一些用法总结
    BigDecimal用法详解
    RabbitMQ 入门 Helloworld
    git标签
    git查看提交历史
    RabbitMQ简介
    【计算机视觉】SeetaFace Engine开源C++人脸识别引擎
  • 原文地址:https://www.cnblogs.com/zwbg/p/6197827.html
Copyright © 2011-2022 走看看