2009-04-21 56 views
21

在非專業術語中垃圾收集機制是如何工作的?垃圾收集機制如何工作?

如何確定一個對象用於垃圾回收?

另外,在GC算法中,Reference Counting, Mark and Sweep, Copying, Train是什麼意思?

+4

沒有......沒有。可能它看起來就像我說的那樣。任何方式 – 2009-04-21 20:16:00

+1

我推薦閱讀相當好的,34頁插圖的論文,[* Uniprocessor Garbage Collection Techniques *,Paul R.Wilson(1992)](http://www.cse.nd.edu/~dthain /courses/cse40243/spring2006/gc-survey.pdf),它解釋了基本垃圾收集技術(引用計數,標記和掃描,標記壓縮,增量,代數)背後的概念。 – stakx 2012-06-16 11:36:16

回答

29

當你使用垃圾收集語言時,你不會直接訪問內存。相反,您可以在數據上訪問一些抽象。被正確抽象出來的東西之一就是數據塊內存的實際位置,以及指向其他數據塊的指針。當垃圾收集器運行時(偶爾會發生這種情況),它將檢查是否仍持有對其分配給它的每個內存塊的引用。如果你不這樣做,它將釋放那個記憶。

垃圾收集器的不同類型之間的主要區別是它們的效率以及它們可以處理什麼樣的分配方案的限制。

最簡單的就是正確引用計數。當您創建對象的引用時,該對象上的內部計數器會遞增,如果偶然引用或它不在範圍內,則(之前)目標對象上的計數器遞減。當這個計數器達到零時,該對象不再被引用並且可以被釋放。

引用計數垃圾收集器的問題是它們無法處理循環數據。如果對象A具有對象B的引用,並且對對象A具有一些(直接或間接)引用,則即使鏈中沒有任何對象在鏈之外被引用,它們也永遠不會被釋放(因此,根本無法訪問該程序)。

另一方面的標記和掃描算法可以處理這一點。標記和掃描算法的工作原理是定期停止程序的執行,將程序分配的每個項目標記爲不可訪問。然後程序運行程序所有的變量,並標記它們指向可達的地方。如果這些分配中的任何一個包含對程序中其他數據的引用,那麼該數據同樣被標記爲可到達等。

這是算法的標記部分。此時所有內容程序可以訪問,無論間接如何,都被標記爲可訪問,程序無法訪問的所有內容都被標記爲不可訪問。垃圾收集器現在可以安全地回收與標記爲不可訪問的對象關聯的內存。

標記和掃描算法的問題在於效率不高 - 必須停止整個程序才能運行它,並且很多對象引用不會改變。

爲了改善這一點,標記和掃描算法可以擴展爲所謂的「分代垃圾收集」。在這種模式下,已經在系統中存在一些垃圾收集數量的對象被提升到舊一代,而不是經常檢查。

這提高了效率,因爲對象往往會年輕化(想象一個字符串在一個循環內部被改變,導致可能終生幾百個循環)或活得很長(用於表示一個對象的主窗口應用程序或servlet的數據庫連接)。

更多詳細信息可以在維基百科上找到。

添加基於評論:

與標記和清除算法(以及除了引用計數的任何其他垃圾收集算法)垃圾回收做在程序的情況下運行,因爲它必須能夠訪問您的程序無法直接訪問的內容。因此,說垃圾收集器在堆棧上運行是不正確的。

3

垃圾收集只是簡單地知道您的程序中是否有將來對變量的需求,如果沒有,則收集並刪除它們。

重點在於這個詞垃圾,你的房子裏被完全使用的東西被扔在垃圾桶裏,垃圾人通過撿起來把它拿走,把它拿走給你更多的空間在你家垃圾桶裏。

引用計數,標記和清除,複製,火車等的在良好的細節在GC FAQ

4
  • 引用計數討論 - 每個對象具有 ,其被遞增時 有人需要到 的引用的計數對象,並在有人 釋放引用時遞減。當引用計數變爲零時,該對象被刪除。 COM使用 這種方法。
  • 標記和掃描 - 如果正在使用每個對象都有一個標記。從對象圖的根部開始(全局變量,堆棧上的本地等),每個引用的對象都會設置標誌,依此類推。最後,刪除圖中未引用的所有對象。

CLR的垃圾收集器在slidedeck中描述。幻燈片15上的「根」是首先進入圖表的對象的來源。他們的成員字段等用於查找圖中的其他對象。

Wikipedia以更多更好的細節描述了其中的幾種方法。

+0

我已經瀏覽了維基百科..實際上困擾我的東西是Object Graph,它是如何被GC程序維護和遍歷的。 – 2009-04-21 20:19:24

0

完成的一般方法是在後臺跟蹤對象的引用次數,當該數字變爲零時,該對象被SUBJECT TO垃圾收集,但GC不會啓動直到明確需要,因爲這是一項昂貴的操作。啓動時發生的事情是,GC通過內存的管理區域並找到沒有剩餘引用的每個對象。 gc通過首先調用它們的析構函數來刪除這些對象,允許它們自行清理,然後釋放內存。通常,GC將通過將每個存活對象移動到一個內存區域來壓縮管理的內存區域,從而允許進行更多的分配。

就像我說的這是我知道的一種方法,並且在這方面有很多研究正在完成。

0

Garbage collection是一個很大的話題,並且有很多方法來實現它。

但簡而言之最常見的,垃圾收集器保持到通過new運營商創造任何東西的所有引用的記錄,即使操作者的使用是從你隱藏(例如,在一個Type.Create()方法)。每次向對象添加新引用時,如果需要,則確定該引用的並將其添加到列表中。只要它超出範圍,就會刪除引用。

當沒有更多的對象引用時,它可以(而不是「將」)被收集。爲了提高性能並確保必要的清理工作正確完成,集合會同時爲多個對象分批處理,併發生在多代之間。