Thinking in Java阅读笔记(二)

第四章 初始化和清理

清理(Cleanup):终结(finalization)与垃圾回收(garbage collection)

Java 提供了垃圾回收器来回收那些不再被使用的对象的内存空间,但是请你想想某些不同寻常的情况。假设你的对象并非经由new获得某种“特殊”内存。

垃圾回收器只知道释放那些经由new分配得来的内存,因此它不知道如何释放你这个对象所占的“特殊”内存。为了应对这种情况,Java提供了一个finalize()函数,你可以为自己的class定义此一函数。

当垃圾回收器打算开始释放你的对象所占用的存储空间时,会先调用其finalize(),并且在下一次垃圾回收动作发生时才回收该对象所占的内存。所以,如果你使用finalize(),它便让你得以在“垃圾回收时刻”执行某些重要的(你自己的)清理动作。

你的对象可能不会被回收

你可能发现,某个对象所占用的空间永远没有被释放掉,因为你的程序可能永远不会逼近内存用完的那一刻。如果你的程序执行完毕,而垃圾回收器完全没有被启动以释放你的对象所占据的内存,那些空间便会在程序终止时才一次归还给操作系统。这是好事,因为垃圾回收器会带来额外负担,如果永远不启动它,就永远不需要付出额外代价。

finalize()存在是为了什么?

垃圾回收动作(garbage collection)只回收内存 也就是说,垃圾回收器存在的唯一理由,就是要回收那些在你程序中再也用不着的内存空间。所以任何和垃圾回收动作捆绑在一起的行为,也都只能和内存或内存的释放相关。这是否意味着如果你的对象内含其他对象,在finalize()中应该明确释放那些对象?答案是no,垃圾回收器所留意的是“对象内存”的释放,不论对象被生成的方式究竟为何。如此一来,对finalize()的需求便局限于特定情况之下。这个情况就是:当你的对象以”对象生成“之外的方式分配了某种存储空间。那么究竟怎样才会碰到上述情况?似乎只有在你通过Java的非政策管道来分配内存,打算做一些类似C会做的事情时,才是使用finalize()的适当时机。这种情况主要发生在采用原生函数时,那是一种在Java程序中调用non-Java程序代码的方法。在non-Java程序代码中,C的malloc()函数族系可能会被调用,用以分配存储空间,而且除非你调用free(),否则其占用空间永远不会被释放,进而产生内存漏洞(memory leak)。当然啦,free()是C/C++函数,所以你得在finalize()中以原生函数加以调用。

阅读至此,你或许明白,你不应该过度使用finalize()。它并不是摆放正常清理动作的合适地点。

如果System.gc()被唤起,终结动作便会发生于所有对象身上。不论System.runFinalization()是否被唤起,似乎都没有任何差别。

死亡条件(The death condition)

一般情况下,你的程序不能依靠“finalize()被调用”才能正常运作。finalize()函数还有一个很有意思的用途,那就是对象的“死亡条件”检查。当你对某个对象不再感兴趣——也就是它可以被清理时——这个对象应该处于某种状态,使它所占用的内存空间得以被安全释放。

class Book{
	boolean checkedOut = false;
	Book(boolean checkedOut){
		this.checkedOut = checkedOut;
	}
	void checkIn(){
		this.checkedOut = false;
	}
	public void finalize(){
		if(checkedOut){
			System.out.println("Error:checked out");
		}
	}
}

public class DeathCondition {

	public static void main(String[] args) {
		Book novel = new Book(true);
		//Proper cleanup
		novel.checkIn();
		//Drop the reference,forget to clean up
		new Book(true);
		//Force garbage collection & finalization
		System.gc();
	}

}
在这个例子中,死亡条件是“所有Book对象都被预期在它们被回收之前先被登录(checked in)”。但在main()中,由于程序员的错误,有一本书未被登录。如果没有finalize()来检查死亡条件,这会是一只棘手的臭虫。请记住,System.gc()被用来强迫终结动作的发生(你应该在程序开发过程中进行此事,以便协助侦错)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值