[英]ASP.NET: Should I be worried about memory leaks in certain situations? [C#]
在兩個對象相互引用的情況下,我關注垃圾收集......
public class A
{ public readonly B _b;
public A()
{ _b = new B(this);
}
}
public class B
{ public readonly A _a;
public B(A objA)
{ _a = objA;
}
}
在這種情況下,第三類可以引用A
...
public class Foo
{ public A _a = new A(); // A and B are both created here.
public void Bar()
{ _a = new A();
} // Create a new A (and B)
}
通常,垃圾收集器會處理不再具有任何活動引用的對象。 但在這種情況下,A和B對象永遠不會丟失所有活動引用,因為它們總是相互引用。
當Foo
對象用新的A
(和B
)替換當前的A
(和B
)時,垃圾收集器是否能夠清除舊的A
(和B
)而不用循環對象引用啟動無限循環?
這是一個嚴重的問題,因為它是一個ASP.NET應用程序。 這些對象將在每個Web請求中多次創建,並且如果垃圾收集器無法清除它們,則可能會延遲服務器重新啟動。
可能的負面結果:
<<由於RAM溢出,Web服務器崩潰。
<< Webserver因無限垃圾收集循環而崩潰。
在這種情況下,.NET如何處理垃圾收集?
.NET GC通過跟蹤有根引用來工作,例如靜態字段和范圍內局部變量。 它正確處理參考周期。 例如,如果A < - > B,但都沒有從有根參考引用,則會收集它。
讓我們考慮GC如何確定它何時可以回收內存。 當CLR嘗試分配內存並且內存不足時,它會執行垃圾回收。 GC枚舉所有有根引用,包括任何線程調用堆棧上的靜態字段和范圍內局部變量。 它將這些引用標記為可訪問,並遵循這些對象包含的任何引用,並將它們標記為可訪問。 它繼續此過程,直到它訪問了所有可訪問的引用。 任何未標記的對象都是不可訪問的,因此是垃圾。 GC壓縮托管堆,整理引用以指向它們在堆中的新位置,並將控制權返回給CLR。 如果釋放了足夠的內存,則使用此釋放的內存繼續分配。 如果不是,則從操作系統請求額外的內存。
如果A - > B,B - > A並且沒有對A和B的其他引用,則GC足夠智能以釋放這些對象。
在ASP.NET中,增加了應用程序池的保險。 應用程序的許多實例保存在內存中,並根據需要分配給各種會話。 有時,即使在會話的上下文中,IIS也會決定刷新應用程序池的好時機。 當會話結束時,IIS通常會關閉並重新啟動應用程序,如果它與每個應用程序,每個池或整個系統內存限制相沖突。 有時這甚至發生在會話中間; 這在SOA中很常見,其中外部Web層通過WCF與另一個服務器通信,並且服務層可以在Web層的調用之間刷新。
.NET Garbage收集器可以毫無問題地清除循環引用。
它不計算對舊VB6 GC等對象的引用。
它通過從特殊的“對象根”開始遍歷內存中的所有對象來跟蹤活動對象。
更簡單地說:
當垃圾收集器運行時,它從內存寄存器和靜態字段等開始。 這些被稱為“根”。
從那里,垃圾收集器跟隨從根到其他對象實例的引用。 這將創建從根可到達的所有對象的圖形。
如果您的對象無法從根目錄訪問,那么它們將被視為未引用,並且可以由垃圾收集器清理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.