【深入學習JVM 04】回收“已死”物件的過程

Coder_Ring發表於2018-08-29

上篇文章講到,虛擬機器判斷一個物件是否可回收是根據“可達性分析”,不可達的物件就是可回收的物件,但是被判定為“不可達的物件”也並非“非死不可”。它們只是被判了“緩刑”,最後是死是生都有可能。

我們看看回收無效物件的過程:

  1. 物件經過可達性分析後,發現沒有被GC Roots關聯,則會被第一次標記

  2. 判斷物件是否覆蓋了finalize方法

如果覆蓋了該方法,並且該物件的finalize方法還沒有執行過。則將這個物件放到F-Queue佇列中,稍後虛擬機器將啟動一個優先順序比較低的Finalizer執行緒去執行finalize方法。

如果沒有覆蓋該方法,或者說finalize方法已經執行過了,則物件就只能等死(等待垃圾收集器將其回收)

  1. 執行F-Queue佇列中等待執行的finalize方法

Finalizer執行緒執行F-Queue佇列中的finalize方法時,將是物件自救的最後一次機會。如果方法的執行使得物件被其他變數或物件所引用,則GC Roots變為可達,GC將會把它移出“即將回收”的物件集合。如果它沒有自救,那它就只能等待回收了。

  1. 回收“即將回收”的集合中的所有物件

垃圾回收器將基於其採用的回收演算法,對無用物件進行回收。

說說finalize方法

從上面的過程中,可以看出,一個類如果定義了finalize方法,在垃圾回收其例項的過程,會先執行finalize方法。

那麼,是不是意味著我們可以再finalize方法中進行資源釋放呢?

這樣做是很危險的。因為在執行F-Queue佇列中的finalize方法時,虛擬機器並不承諾完整地執行完整個方法。因為如果finalize方法中執行的操作比較耗時,虛擬機器將終止它以保證佇列中其他finalize方法能夠及時執行。

因此,釋放資源還是選擇try - finally的方式吧。

另外,物件自救的方法也不建議利用finalize方法,因為finalize只會被系統呼叫一次,物件可能活過第一次,但是卻可能活不過第二次的垃圾回收,因為第二次時finalize將不再執行。

總之,finalize方法瞭解就好,實際情況中不建議使用。

點贊是對我最大的鼓勵

相關文章