Java对象与垃圾回收

Java中创建引用类型对象时,都会在堆内存中分配一块区域,Java对象就保存在这块内存区域中,当这块内存区域不再被任何变量引用时,垃圾回收机制就会把这块内存区域回收。


1 垃圾回收机制的特征

垃圾回收机制只负责回收堆内存中的对象。

垃圾回收机制根据回收策略运行,程序无法精确控制。

在回收Java对象之前,会先调用该对象的finalize()方法。


2 Java对象在内存中的状态

Java对象在堆中运行时有三种状态:可达状态、可恢复状态、不可达状态。

可达状态:Java对象被创建后,如果被一个或多个变量引用,那么这个Java对象处于可达状态,即这个对象可以被访问。

可恢复状态:Java对象不再被任何变量引用就进入了可恢复状态。在这种状态下,垃圾回收机制准备回收该对象所占用的资源,在回收该对象之前,该对象的finalize()方法进行资源清理。如果在finalize()方法中重新让变量引用该对象,则该对象再次变为可达状态,否则该对象进入不可达状态。

不可达状态:Java对象不被任何变量引用,且系统在调用对象的finalize()方法后依然没有使该对象变成可达状态(该对象依然没有被变量引用),那么该对象将变成不可达状态。当Java对象处于不可达状态时,系统才会真正回收该对象所占有的资源。


3 强制垃圾回收

Java程序无法精确控制Java垃圾回收的时机,但是依然可以强制进行垃圾回收,也就是通知系统进行垃圾回收,但系统何时进行垃圾回收无法确定。不过垃圾回收机制也不会对程序的垃圾回收命令完全不理,垃圾回收机制在收到通知后会尽快进行垃圾回收。强制垃圾回收有两种方法:①调用System类的gc()静态方法。②调用Runtim对象的gc()实例方法。


public class GcDemo {
	private int index;
	
	public GcDemo(int index){
		this.index = index;
	}

	public static void main(String[] args) {
		for(int i = 0; i < 5; i++){
			new GcDemo(i);
			//下面两行代码的作用完全相同,强制系统进行垃圾回收
			//Runtime.getRuntime().gc();
			System.gc();
		}
	}
	
	public void finalize(){
		System.out.println("正在清理第 " + index + "个GcDemo...");
	}
}
/*
程序执行的结果如下:
正在清理第 3个GcDemo...
正在清理第 0个GcDemo...
正在清理第 1个GcDemo...
正在清理第 2个GcDemo...
正在清理第 4个GcDemo...
垃圾回收并不是严格按照顺序执行的,也就是说垃圾回收不是实时的,而是根据垃圾回收机制在合适的时间触发。
*/


4 finalize()方法

在回收Java对象占用的内存之前,通常会调用适当的方法清理资源,默认情况下会调用finalize()方法来清理该对象的资源。finalize()方法在Object类中定义,在finalize()方法被调用后,垃圾回收机制开始执行。Object类的finalize()方法可以在继承类中重写(Override),用来清理继承类的资源。finalize()方法具有以下特点:

不要主动调用finalize()方法,该方法应该交给垃圾回收机制调用。

finalize()方法无法确定何时被调用,因此finalize()方法不一定会执行。

当JVM(Java虚拟机)调用finalize()方法时,可能使该对象变成可达状态。

当JVM(Java虚拟机)调用finalize()出现异常时,垃圾回收机制不会报告异常,程序继续执行。

public class FinalizeDemo {
	private static FinalizeDemo fd = null;
	private int index;
	
	public FinalizeDemo(int index){
		this.index = index;
	}
	
	public void print(){
		System.out.println("FinalizeDemo " + index);
	}

	public static void main(String[] args) throws InterruptedException {
		new FinalizeDemo(5);
		System.gc();
		
		//暂停2秒,以便系统进行垃圾回收。
		//如果不执行①语句,那么②语句会比finalize方法先执行,这时FinalizeDemo.fd还未赋值。
		Thread.sleep(2000); //①
		try{
			FinalizeDemo.fd.print();  //②
		}catch(Exception e){
			System.out.println("Error:" + new Date().getTime());
		}		
	}
	
	public void finalize(){
		System.out.println("正在清理FinalizeDemo " + index + " :" + new Date().getTime());
		fd = this;
	}
}
/*
程序执行的结果如下:
正在清理FinalizeDemo 5 :1400316264637
FinalizeDemo 5

垃圾回收先执行finalize()方法,然后把对象赋给FinalizeDemo.fd。

如果把①语句注释掉,程序执行结果如下:
Error:1400316599948
正在清理FinalizeDemo 5 :1400316599948

发现②语句会比finalize()方法先执行,也就是还没有进行垃圾回收,②语句就已经执行了。
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值