📜  Java程序的输出 |第 10 组(垃圾收集)

📅  最后修改于: 2022-05-13 01:55:16.400000             🧑  作者: Mango

Java程序的输出 |第 10 组(垃圾收集)

先决条件 - Java中的垃圾收集

难度级别:中级
在Java中,垃圾收集器模块负责对象销毁,并且没有对它们的任何引用的对象有资格进行垃圾收集。以下是有关垃圾收集的一些重要输出问题。
预测以下Java程序的输出:

  • 程序 1:
    public class Test
    {
        public static void main(String[] args) throws InterruptedException
        {
            String str = new String("GeeksForGeeks");
                  
            // making str eligible for gc
            str = null; 
                  
            // calling garbage collector
            System.gc(); 
                  
            // waiting for gc to complete
            Thread.sleep(1000); 
          
            System.out.println("end of main");
        }
      
        @Override
        protected void finalize() 
        {
            System.out.println("finalize method called");
        }
    }
    

    输出:

    end of main
    

    解释:我们知道垃圾收集器在销毁对象之前会调用 finalize() 方法。但在这里,诀窍在于 str 是 String 类对象,而不是 Test 类。因此,在 str 上调用 String 类的 finalize() 方法(如果在 String 类中被覆盖)。如果一个类没有覆盖 finalize 方法,则默认调用 Object 类的 finalize() 方法。

  • 方案二:
    public class Test
    {
        public static void main(String[] args) throws InterruptedException
        {
            Test t = new Test();
                  
            // making t eligible for garbage collection
            t = null; 
                  
            // calling garbage collector
            System.gc(); 
                  
            // waiting for gc to complete
            Thread.sleep(1000); 
          
            System.out.println("end main");
        }
      
        @Override
        protected void finalize() 
        {
            System.out.println("finalize method called");
            System.out.println(10/0);
        }
          
    }
    

    输出:

    finalize method called
    end main
    

    解释 :
    当垃圾收集器在对象上调用 finalize() 方法时,它会忽略该方法中引发的所有异常,程序将正常终止。

  • 程序 3:
    public class Test
    {
        static Test t ;
          
        static int count =0;
          
        public static void main(String[] args) throws InterruptedException
        {
            Test t1 = new Test();
                  
            // making t1 eligible for garbage collection
            t1 = null; // line 12
                  
            // calling garbage collector
            System.gc(); // line 15
                  
            // waiting for gc to complete
            Thread.sleep(1000); 
          
            // making t eligible for garbage collection,
            t = null; // line 21
                  
            // calling garbage collector
            System.gc(); // line 24
          
            // waiting for gc to complete
            Thread.sleep(1000); 
                  
            System.out.println("finalize method called "+count+" times");
              
        }
          
        @Override
        protected void finalize() 
        { 
            count++;
              
            t = this; // line 38
                  
        }
          
    }
    

    输出:

    finalize method called 1 times
    

    解释 :
    执行第 12 行后,t1 就可以进行垃圾回收了。所以当我们在第 15 行调用垃圾收集器时,垃圾收集器会在销毁 t1 之前调用 finalize() 方法。但是在 finalize 方法中,在第 38 行,我们再次通过 t 引用同一个对象,因此在执行第 38 行之后,该对象不再符合垃圾回收条件。因此,垃圾收集器不会销毁对象。

    现在再次在第 21 行,我们让同一个对象再次符合垃圾回收的条件。在这里,我们必须清楚关于垃圾收集器的一个事实,即它会在特定对象上调用 finalize() 方法恰好一次。由于在这个对象上已经调用了 finalize() 方法,所以现在垃圾收集器将销毁它,而无需再次调用 finalize() 方法。

  • 程序 4:
    public class Test
    {
        public static void main(String[] args)
        {
            // How many objects are eligible for 
            // garbage collection after this line?
            m1();  // Line 5
        }
      
        static void m1() 
        {
            Test t1 = new Test();
            Test t2 = new Test();
        } 
    }
    

    问题 :
    执行第 5 行后有多少对象符合垃圾回收条件?
    回答 :

    2
    

    解释 :
    由于 t1 和 t2 是 m1() 方法的本地对象,因此它们在方法执行完成后才有资格进行垃圾回收,除非它们中的任何一个被返回。

  • 方案 5:
    public class Test
    {
        public static void main(String [] args) 
        {
            Test t1 = new Test();
            Test t2 = m1(t1); // line 6
            Test t3 = new Test();
            t2 = t3; // line 8
              
        }
          
        static Test m1(Test temp) 
        {
            temp = new Test();
            return temp;
        }
    }
    

    问题 :
    执行第 8 行后有多少对象符合垃圾回收条件?
    回答 :

    1
    

    解释 :
    到第 8 行执行时,唯一没有引用的对象是第 6 行生成的对象。请记住“Java严格按值传递”,因此引用变量 t1 不受 m1() 方法的影响.我们可以使用 finalize() 方法检查它。 finalize() 方法中的语句“System.out.println(this.hashcode())”打印调用 finalize() 方法的对象 hashcode 值,然后将该值与 main 方法中创建的其他对象 hashcode 值进行比较.