天天看點

Java的finalize()

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)又或者打開的檔案資源,這些資源不屬于垃圾回收器的回收範圍。