Java的finalize()
首先,我们都了解初始化的重要性,但是常常会忘记同样也重要的清理工作。Java有垃圾回收器负责回收无用对象占用的内存资源。但是也有特殊情况:假定你的对象(并非使用new)获得一块“特殊”的内存区域,由于垃圾回收器只知道释放那些经由new分配的内存,所以它不知道如何释放该对象的这块特殊内存。为了应对这种情况,Java允许在类中定义一个名为finalize()方法。
Java的finalize()不同于C++里的析构函数:
1.对象可能不被垃圾回收,
2.垃圾回收并不等于析构。
所以在Java中你不需要某个对象之前,如果必须执行某些动作,那么必须手动创建一个方法去做这些操作。
那么finalize9)真正用处是什么?这里引出第三点:
3.垃圾回收只与内存有关。
也就是说,使用垃圾回收器唯一的原因是为了回收程序不再使用的内存。之所以要有finalize(),是由于再分配内存时可能采用了类似C语言的做法,而非Java中的通常做法。这种情况主要发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。本地方法目前只支持C和C++,但是它们可以调用其他语言写的代码,所以实际上可以调用任何代码。在非Java代码中你也许会调用C的malloc()函数系列来分配存储空间,而且除非调用了free()函数,否则存储空间将得不到释放,从而造成内存泄漏。而这些需要在finalize()中用本地方法调用它。
所以通常我们的“清理”工作并不能指望finalize()方法。
finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?
一旦垃圾回收器准备好释放对象占用的存储空间,首先会去调用finalize()方法
①进行一些必要的清理工作(对垃圾回收器不能处理的特殊情况进行处理)(例子在下边)
②也有可能使该对象重新被引用,我习惯叫这种作用为复活。注意!!每个对象的finalize()方法只能被执行一次,第二次就会直接跳过finalize()方法,这就是为了防止出现对象无限复活,内存空间只增不减。
一般忽略第二种情况,概念就变成了:一旦垃圾收集器准备好释放对象占用的存储空间(进入第一个回收周期),首先会去调用finalize()方法进行一些必要的清理工作,只有到下一次再进行垃圾回收动作(下一个回收周期)的时候,才会真正释放这个对象所占用的内存空间。
例子:1)由于在分配内存的时候可能采用了类似 C语言的做法,而非JAVA的通常new做法。这种情况主要发生在native method中,比如native method调用了C/C++方法malloc()函数系列来分配存储空间,但是除非调用free()函数,否则这些内存空间将不会得到释放,那么这个时候就可能造成内存泄漏。但是由于free()方法是在C/C++中的函数,所以finalize()中可以用本地方法来调用它。以释放这些“特殊”的内存空间。
2)又或者打开的文件资源,这些资源不属于垃圾回收器的回收范围。