Java面试中经常会遇到一个问题:final、finally、finalize的区别?
今天我只谈大家回答的最不准确也误解最深的一个 —— finalize。谈finalize() 方法之前需要先了解一下Java垃圾回收机制。
Java有垃圾回收期负责回收无用对象占据的内存资源。但也有特殊情况:假定你的对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道释放那些经由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。【gc只负责jvm内部分配的资源,所以如果通过jni获取了系统资源,肯定无法自动回收. 】, 为了应对这种情况,java允许在类中定义一个名为finalize()的方法。它的工作原理“假定”是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize() 方法,并且在下一次垃圾回收动作发生时,才真正回收对象占用的内存。
?
?
这里有一个编程陷阱:基于上述对finalize的理解,很容易把finalize和C++中的析构函数对应起来。其实他们两个很不一样,在C++中,对象一定会被销毁;而java里的对象却并非总是被垃圾回收器回收。也许你会发现,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。(因为垃圾回收本身也有开销,要是不使用它就不用支付这部分开销了)
?
finalize()的真正用途:
之所以要有finalize(),是由于在分配本地内存时可能采用了类似C语言中的做法,而非Java中的通常做法。这种情况主要发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。本地方法目前只支持C和C++,但它们可以调用其他语言写的代码,所以实际上可以调用任何代码。在非Java代码中,也许会调用C的malloc()函数系列来分配存储空间,而且除非调用了free()函数,否则存储空间将得不到释放,从而造成内存泄露。当然,free()是C和C++中的函数,所以要在finalize()中用本地方法调用它。
?
至此,或许明白了finalize的确实不是进行普通的清理工作,对于开头提到的面试问题,如果可以根据自己对本文描述内容的理解予以回答,也已足够。
?
?
?
?
?
?
?
?
?
?
?