2012-01-01 45 views
2

在.net中爲什麼Garbage collector在超出範圍時不會銷燬對象?它爲什麼要等到下一個清理過程運行?爲什麼物體一旦超出範圍就不清洗?

+2

在這裏有一篇關於.Net垃圾回收器的好文章:http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/ – 2012-01-01 16:40:01

回答

8

這是一個由Chris Sells和Chris Tavares於2003年秋季開展的項目,由微軟贊助。他們通過向每個對象添加引用計數字段並修改JIT編譯器,以便在引用超出範圍時自動減少計數,從而修改CLR(轉子版本)。當計數變爲零時自動運行終結器。

目標達到了,不再需要使用聲明。

手術成功,但病人死了。這些修改導致嚴重的性能下降。他們試圖診斷它,並在當時是領先的工具供應商的Compuware的幫助下呼籲。但不能釘住它。該博客文章發佈失敗is here,技術細節are here

垃圾收集器在此之後得到了更多的尊重。自那時以來,我不知道進一步的嘗試。

+0

我希望我能「收藏」答案... – Mehrdad 2012-01-14 02:50:06

0

該應用程序/系統可能正在忙於做其他事情。因此,立即進行GC運行可能會導致性能下降。系統會嘗試確定運行GC的最佳時間。

3

這將需要GC的引用計數形式。 .NET GC是mark-and-sweep類型。

對象不會超出範圍。對象的引用可以。編譯器可以很容易地跟蹤它,但是還有其他對同一個對象的引用嗎?這並不是微不足道的。

引用計數有2個主要問題:

  1. 編譯器生成額外的代碼每次引用傳遞,複製或刪除
  2. 當兩個物體互相引用您有內存泄漏的時間。
+0

假設你聲明一個實例變量部門d1 = new department();現在,一旦d1超出範圍,哪個內存位置d1指向的內存不再可用。你可以給我一個情況,那是不正確的? – developer747 2012-01-01 16:52:02

+1

假設構造函數'new Department()'將自己註冊到一個靜態列表中。 – 2012-01-01 16:59:32

+0

@ user1110437「return d1;」怎麼樣? – Iridium 2012-01-01 16:59:42

0

那麼,不是過程,而是線程。

主要原因是性能:垃圾收集的過程很昂貴,因此「虛擬機」更喜歡留下一些「誤入歧途」的內存(好吧,不是真的:它仍然可以引用它)併爲新的內存分配內存需要時的對象。不過,它仍然會定期運行,因爲讓記憶迷失太久也無濟於事。

垃圾收集算法很多:請參閱here。垃圾收集算法的目的是儘可能少地從運行代碼吸血鬼。在物品超出範圍後立即收集垃圾並不適合該帳單...

0

因爲那麼每次對任何引用(對象成員,變量,集合項目等)進行分配/更改時都需要進行檢查。你需要跟蹤對象的所有引用,例如通過存儲計數並使其保持最新。這被稱爲引用計數,並且具有許多問題,從一般性能(每個引用分配需要比較和存儲器訪問)到存在併發時的同步開銷(如果兩個線程同時引用同一對象的引用會發生什麼?)以無法檢測週期(如果A指的是B和B指的是A,則兩個參考計數都不能降爲0,因此您泄漏內存或者仍然需要如下所述的「完整」GC)。

相反,大多數的垃圾收集器只是讓引用來來去去,如果他們需要收集,他們按照當前存在以確定哪些對象是使用(分別爲引用,可能被使用,因爲它們是可到達)並將其餘部分解除分配。顯然,這是很多工作,所以你只是偶爾做一次。還有一些更加精細的方法可以最大限度地減少平均收集的工作量,或者更傾向於收集更可能堆的區域。但一般問題仍然存在:一旦垃圾變成垃圾,你就找不到所有的垃圾,因爲這意味着每當參考變化時,就會遍歷整個垃圾堆。

相關問題