關於將臨時變數置為null是否有助於快速垃圾回收

NO IMAGE

“將不再使用的臨時變數立即置為null是否有助於垃圾回收”的話題好像有不少人爭論過。

首先,我們要理解GC回收垃圾資料的標準是通過路徑檢查,看是否還有引用指向某個物件。如果不再有引用指向這個待回收的物件,那麼GC會將其放入待回收佇列。從這個理論上來說,適時將不再使用的變數置為null是有助於垃圾回收的。但是,進一步理解GC的工作模式,我們會發現如下幾個問題。

1. GC只是將其置於待回收佇列,並不一定立即回收(需要一定的條件)。
2. GC並不會在變數置為null時啟動回收動作。

所以只有在某個理想狀態下,這個null才有助於GC回收。因此我個人並不推薦這樣的編碼方式,無論從程式碼的優雅性還是效率上都無助於效能提升。當然對於非常消耗資源的物件,建議使用IDisposable介面和using關鍵字。

 

關於GC的一些補充:

1. GC只回收託管堆上的物件。
2. 每個應用程式都有一些根,諸如全域性變數或者靜態變數。
3. GC通過遍歷所有的根來檢查所有物件是否可達,從而判斷哪些物件依然被引用,其餘的則是可回收物件。
4. GC會尋找較大的連續可回收區塊,並將其他一些非垃圾物件搬移到此處,從而壓縮託管堆。
5. GC只有在0代物件充滿、記憶體不足或者呼叫Collect方法時才會執行回收動作,以避免頻繁回收造成效能損傷。
6. CLR託管堆支援3個代齡:第0代,第1代,第2代。每級代齡都有一定大小的闕值。
7. 剛初始化的託管堆,所包含的物件都是第0代。當分配的物件超過了第0代設定的闕值時,會進行垃圾回收,並把存活的物件提升為第1代物件,第0代空缺。隨著程式執行,繼續分配第0代物件,當超過闕值時執行第2次垃圾回收,在回收前會檢查第1代闕值是否超出,如果超出則先回收第1代物件中可回收垃圾,並將存活下來的物件提升為第2代齡物件。然後繼續回收第0代,並相應地將第0代生存下來的物件提升為第1代齡物件。如此反覆,從而最大程度上回收那些第0代的活躍可回收物件,從而提高GC效能。
8. GC是自我調節的,會根據系統具體狀況調節不同代齡的闕值,以此來提高回收效率。