【转】.net框架读书笔记---CLR内存管理\垃圾收集(五)
對象復蘇
??? 當一個終止化對象被認為死亡時,垃圾收集器可以強制使該對象獲得重生(進入終止化可達隊列),因為這樣才能調用對象的Finalize方法。在Finalize方法被調用之后,它才算真正的死亡了,一個終止化對象會經歷死亡,重生然后再死亡的過程。該現象被稱為復蘇(resurrection)
- 垃圾收集器將對象的引用放到終止化可達隊列,對象可達,獲得了重生;
- 調用對象的Finalize方法后,再沒有任何根指向對象,對象真正的死亡。
在對象的Finalize方法中將其指針再放入全局靜態變量中,會怎么樣??
?
namespace?ResurrectionStudy
{
class?Program
{
static?void?Main(?string?[] args)
{
SomeType s?=?new?SomeType();
}
}
class?SomeType
{
~?SomeType()
{
Console.WriteLine(?"?Finalize?"?);
MyApplication.objHandler?=?this?;
}
}
class?MyApplication
{
public?static?object?objHandler;?//?默認為null
}
}
當執行Finalize時,該對象的一個引用將被放入一個根中,從而使其可達,對象重新復蘇后垃圾收集器將不會認為其是可收集的垃圾。但是必須記住該對象已經被執行終止化了,使用可能會導致不可預期的結果。如果SomeType還引用了其他對象的字段的話,會使被引用的對象都重新復蘇,但是這些重新復蘇的對象中可能一些已經被執行了終止化。
一個不斷復蘇,永不死亡的對象。使用GC的ReRegisterForFinalize方法將指定對象添加到終止化鏈表的末端,會使對象的Finalize方法將再一次被調用。
namespace?ResurrectionStudy
{
class?Program
{
static?void?Main(?string?[] args)
{
SomeType s?=?new?SomeType();
}
}
class?SomeType
{
~?SomeType()
{
Console.WriteLine(?"?Finalize?"?);
MyApplication.objHandler?=?this?;
GC.ReRegisterForFinalize(?this?);
}
}
class?MyApplication
{
public?static?object?objHandler;?//?默認為null
}
}
?
純屬娛樂,如果有需要可以在終止化方法內部根據一定的條件使對象重新復蘇。
利用對象復蘇設計一個對象池
對象復蘇還是很有用的。假設創建一個Expensive對象池。由于對象非常耗費資源,創建他需要花費很多的時間,出于性能考慮,打算在應用程序啟動之后就能創建一組Expensive對象,然后在應用程序整個生存期中重復地使用。
?
namespace?ResurrectionStudy
{
class?Expensive
{
static?Stack pool?=?new?Stack();
//?從對象池中獲取對象
public?static?Expensive GetObjectFromPool()
{
return?(Expensive)pool.Pop();
}
//?應用程序關閉時調用該方法,銷毀對象池
public?static?void?ShutdownThePool()
{
//?阻止終止化對象被加入對象池
pool?=?null?;
}
//?創建一個對象并將其添加到對象池中
public?Expensive()
{
pool.Push(?this?);
}
//?當應用程序不再使用對象時,Finalize將會被調用
~?Expensive()
{
//?如果應用程序沒有被關閉,將對象重新添加到對象池
if?(pool?!=?null?)
{
//?調用ReRegisterForFinalize方法使對象以正確的狀態加入到對象池
GC.ReRegisterForFinalize(?this?);
pool.Push(?this?);
}
}
}
}
?
當應用程序不再持有Expensive對象的引用,如果出現垃圾回收,那么Expensive將會被終止化。當Expensive對象的Finalize方法被調用后,它會將自己再次加入到對象池中,從而使其復蘇,阻止垃圾收集器回收其內存。
當退出應用程序時,將pool字段設為null,當應用程序關閉時,CLR會為托管堆上的所有對象調用Finalize方法。因為這樣子會導致無線循環(CLR會在40后強制中斷進程)。如果pool為null,那么Expensive對象將不會再被添加到終止化鏈表上,同時也不會被添加到對象池中,Expensive的內存將會被回收。
總結
以上是生活随笔為你收集整理的【转】.net框架读书笔记---CLR内存管理\垃圾收集(五)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 画面补丁翻车严重:《生化危机》多部作品遭
- 下一篇: 广东暴雨 夫妻连人带车被冲走正搜救:视频