这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

可以先看我昨天写的这篇文章了解- Java 中的垃圾回收机制

难度级别: 中级
在 Java 中,对象销毁由垃圾收集器模块负责,没有任何引用的对象有资格进行垃圾收集。下面是一些关于垃圾收集的重要输出问题。

程序

程序一

预测以下 Java 程序的输出:

public class Test
{
	public static void main(String[] args) throws InterruptedException
	{
		String str = new String("Haiyong");
			
		// 使 str 符合 gc 的条件
		str = null;
			
		// 调用垃圾收集器
		System.gc();
			
		// 等待 gc 完成
		Thread.sleep(1000);
	
		System.out.println("end of main");
	}

	@Override
	protected void finalize()
	{
		System.out.println("调用的finalize方法");
	}
}
复制代码

点此跳转到答案

程序二

public class Test
{
	public static void main(String[] args) throws InterruptedException
	{
		Test t = new Test();			
		// 使 t 有资格进行垃圾收集
		t = null;			
		// 调用垃圾收集器
		System.gc();			
		// 等待 gc 完成
		Thread.sleep(1000);	
		System.out.println("end main");
	}
	@Override
	protected void finalize()
	{
		System.out.println("调用的finalize方法");
		System.out.println(10/0);
	}	
}
复制代码

点此跳转到答案

程序三

public class Test
{
	static Test t ;	
	static int count =0;	
	public static void main(String[] args) throws InterruptedException
	{
		Test t1 = new Test();			
		// 使 t1 有资格进行垃圾收集
		t1 = null; // line 12			
		// 调用垃圾收集器
		System.gc(); // line 15			
		// 等待 gc 完成
		Thread.sleep(1000);	
		// 使 t 有资格进行垃圾收集
		t = null; // line 21			
		// 调用垃圾收集器
		System.gc(); // line 24	
		// 等待 gc 完成
		Thread.sleep(1000);			
		System.out.println("调用finalize方法 "+count+" 次");		
	}	
	@Override
	protected void finalize()
	{
		count++;		
		t = this; // line 38			
	}	
}
复制代码

点此跳转到答案

程序四

public class Test
{
	public static void main(String[] args)
	{
		// 此行之后有多少对象符合垃圾回收条件?
		m1(); // Line 5
	}

	static void m1()
	{
		Test t1 = new Test();
		Test t2 = new Test();
	}
}
复制代码

点此跳转到答案

程序五

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;
	}
}
复制代码

点此跳转到答案


文章后半部分是程序的输出及解析

【Java练习题】Java 程序的输出 | 第十套(垃圾回收)_后端

【Java练习题】Java 程序的输出 | 第十套(垃圾回收)_后端_02


输出及解析

程序一输出

输出

end of main
复制代码

解释

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

程序二输出

输出

调用finalize方法
end main
复制代码

说明

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

程序三输出

输出

调用finalize方法 1 次
复制代码

说明

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

现在再次在第 21 行,我们再次使同一对象有资格进行垃圾回收。在这里,我们要明确有关一个事实有关垃圾收集器,即它会调用finalize()方法的特定对象恰好在一个时间。由于在这个对象上已经调用了 finalize() 方法,所以现在垃圾收集器将销毁它,而无需再次调用 finalize() 方法。

程序四答案

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

回答 :

2
复制代码

说明

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

程序五答案

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

回答 :

1
复制代码

说明:

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


以上就是本篇文章的所有内容了