• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    .NET中的垃圾回收

    發布: 2007-6-14 17:33 | 作者: 網絡轉載 | 來源: 網絡 | 查看: 22次 | 進入軟件測試論壇討論

    領測軟件測試網

    MILY: 黑體; mso-ascii-font-family: Arial">目錄

    l         導言

    l         關于垃圾回收

    l         垃圾回收算法

    m        應用程序根(Application Roots

    l         實現

    m        階段I: 標記(Mark

    m        階段II: 整理(Compact

    l         終結(Finalization

    l         垃圾回收性能的優化

    m        弱引用(WeakReference

    m        代(Generations

    l         垃圾回收相關的神話

     

    導言

           微軟聲稱.NET是一種革命性的編程技術。許多要素使它成為大多數開發人員的首選。本文我們將要討論一下.NET Framework中一個很主要的優勢——內存和資源管理的便捷性。

     

    關于垃圾回收器

           每個程序都會使用一定次序的資源,或內存緩沖區,或網絡連接,或數據庫資源等等。實際上,在面向對象環境中,每種類型都被看作是程序的某些有效資源。為了使用這些資源,必須分配部分內存來描述這種類型。

     

           資源訪問按一下步驟進行:

     

    1.    為類型分配內存來描述資源。

    2.    初始化資源,把資源設置成初始化狀態,使資源可用。

    3.    通過訪問類型實例的成員來使用資源(按需求重復)。

    4.    銷毀資源狀態以清除資源。

    5.    釋放內存。

     

    .NET中的垃圾回收器(GC)完全徹底幫助開發人員從追蹤內存的使用和確定什么時候釋放內中解脫出來。

     

    Microsoft® .NET CLR (公共語言運行庫)要求所有資源都從托管堆中進行分配。你無需釋放托管堆中的對象——當應用程序不再需要這些對象時,對象將被自動釋放。

     

    內存不是無限的。垃圾回收器需要執行回收以便釋放內存。垃圾回收器的優化引擎會對已做的分配選擇最好的回收時間(準確標準由微軟提供)。當垃圾回收器執行回收時,它先找出托管堆中不再被應用程序使用的對象然后執行相應操作收回這些對象的內存空間。

     

           然而,為了進行自動內存管理,GC必須知道根的位子。也就是說,它應該知道一個對象什么時候不再被應用程序使用了。在.NET中,GC是通過一個稱之為元數據的東西了解到這些的。.NET中使用的每種數據類型都通過元數據來描述它。在元數據的幫助下,CLR知道內存中每個對象的布局,在垃圾回收的整理階段給GC提供幫助。沒有這些信息,GC將不會知道一個對象在哪兒結束和下一個從哪兒開始。

     

    垃圾回收算法

    應用程序根(Application Roots

           每個應用程序都有一套根(Roots)。根標識存儲位置,這個位置或者指向一個托管堆的對象,或者指向一個空對象(null)。

     

    比如:

     

    l         一個應用程序中所有全局和靜態對象指針。

    l         一個線程堆棧中所有局部變量/參數對象指針。

    l         托管堆中所有CPU登記的對象指針。

    l         FReachable隊列中的對象指針。

     

    活動根的表由JIT編譯器和CLR維護,并且對于垃圾回收器的算法是訪問。

     

    實現

    .NET中的垃圾回收是用跟蹤回收實現的,確切的說CLR實現了標記(Mark)/整理(Copact)回收器。

     

    這個方法有以下兩個階段組成:

     

    階段I:標記(Mark

    找到可以被收回的內存。

     

    GC開始運行時,它假設堆中的所有對象都是垃圾。換句話說,它假設應用程序的根沒有指向堆中的的任何對象。

     

    階段I中包含下列步驟:

     

    1.  GC識別存活對象的引用或應用程序根。

    2.  從根開始遍歷,建一張可以從根遍歷的所有對象的圖。

    3.  如果GC準備嘗試添加一個已經在圖中的對象,它就停止這條路徑的遍歷。這樣做有兩個目的,第一個是極大的優化性能,因為它不會遍歷一套對象一次以上。第二是防止當有對象的循環連接列表時而發生死循環,因此循環被有效的控制了。

     

    一旦所有的根都被檢查完后,垃圾回收器的圖中包含了所有可以從應用程序根遍歷到的對象。任何不再圖中的對象都不能被應用程序訪問到,也就是所謂的垃圾。

     

    階段II:整理(Compact)

    把所有存活的對象移到堆的末端,空出堆頂端的空間。

     

    階段II包含下列步驟:

     

    1.  現在GC線性地遍歷堆,尋找鄰近的垃圾對象塊(現在被認為是空閑空間)。

    2.  然后GC往下移動內存中的非垃圾對象,去掉堆中的所有空隙。

    3.  移動內存中的對象導致對象指針失效。因此GC需要修改應用程序的根使對象的指針指向新的位置。

    4.  另外,如果對象包含一個指向其它對象的指針,GC也會負責糾正這些指針。

     

    在所有垃圾被標識完以后,所有的非垃圾對象也被整理,并且所有非垃圾對象的指針也被修正,最后一個非垃圾對象后的指針指向下一個被添加對象的位置。

     

    終結(Finalization)

     

    .NET Framework的垃圾回收器能暗中追蹤由應用程序創建的對象的生命周期,但是當它遇到對象包裝了非托管資源(比如文件、窗口或網絡連接等)時卻無能為力。

     

    一旦應用程序不再使用那些非托管資源時需要顯示地釋放它們。.NET Framework為對象提供了終結(Finalize)方法:在垃圾回收器收回這個對象的內存時,必須執行對象的這個方法來清除它的非托管資源。由于缺省的Finalize方法什么都沒做,如果需要顯示清除資源必須覆蓋這個方法。

     

    如果一把Finalize方法當作只是C++中析構函數另外一個名字那也不足為怪。雖然它們都被賦予了釋放對象占有的資源的任務,但是它們還是有很不相同的語義。在C++中,當對象推出作用域時析構函數會立刻被調用,而Finalize方法是在起動垃圾回收清除對象時才被調用的。

     

    .NET中,由于終結器(Finalizer)的存在使得垃圾回收的工作變得更加復雜了,因為它在釋放對象前增加了許多額外的操作。

     

    無論什么時候,在堆上分配一個含有Finalize方法的新對象時,都會有一個指向這個對象的指針被添加到一個稱為Finalization隊列的內部數據結構當中。當對象不能再次被遍歷到時,GC就認為這個對象是垃圾。GC首先掃描Finalization隊列查找這些對象的指針,當指針被找到時,把它從Finalization隊列中去掉并添加到另外一個名為FReachable隊列的內部數據結構中,使這個對象不再是垃圾的一部分。這時,GC完成了確定垃圾。然后整理(Compact)可收回的內存,由專門的線程負責清空FReachable隊列并執行對象的Finalize方法。

     

    第二次垃圾回收器被觸發的時候,它把被終結(Finalize)的對象看作真正的垃圾,然后簡單的釋放它們的內存。

     

    由此可知當一個對象需要終結時,它先死,然后存活(復活),然后再次并且最終地死去。推薦避免使用Finalize方法,除非有需要。Finalize方法會增加內存壓力,因為直到兩次垃圾回收被啟動時,對象占用的內存和資源才會得到釋放。因此你無法控制兩次Finalize方法執行的順序,它可能會導致無法預料的后果。

    垃圾回收性能的優化

    l         弱引用(WeakReference

    l         代(Generations

     

    弱引用(WeakReference

           弱引用(WeakReference)是提高性能的一種方式,用于減少托管堆中大對象的壓力。

          

           當一個根指向一個對象時,它被稱為這個對象的一個強引用并且這個對象不能被回收,因為應用程序能遍歷到這個對象。

     

           當一個對象有一個指向它的弱引用(WeakReference)時,基本上是指如果有內存請求并且GC啟動時,這個對象可以被回收,當應用程序再次嘗試去訪問這個對象時,訪問將會失敗。另一方面,為了能訪問一個被弱引用(WeakReference)的對象,應用程序必須獲得一個對這個對象的強引用。如果應用程序在垃圾回收器回收這個對象之前獲得了它的強引用,GC將不能回收這個對象,因為有這個對象的強引用存在。

     

           托管堆包含兩個管理弱引用(WeakReference)的內部數據結構:短弱引用表和長弱引用表。

     

           兩種類型的弱引用:

     

    l         短弱引用不追蹤復蘇。

    也就是說,一個有短弱引用的對象會被立即收回,而不用等到運行Finalize方法。

    l         長弱引用追蹤復蘇。

    也就是說,只有當長弱引用表中的對象的存儲空間可收回的時候GC才回收這個對象。如果對象有Finalize方法,是在Finalize方法被調用了之后并且對象不能復活了。

     

           這兩個表簡單的存放著分配在托管堆中對象的指針。最初,兩個表均為空。當你創建一個弱引用(WeakReference)對象時,對象不從托管堆中分配。而是在一個弱引用表中分配一個空的存儲位置;短弱引用使用短弱引用表,長弱引用使用長弱引用表。

     

           讓我們看一個例子,看看GC運行時會發生些什么。下面的圖(圖1和圖2)顯示了GC運行前和運行后所有內部數據結構的狀態。

     

    1GC運行前

     

    2GC運行后

     

    以下是GC運行時進行的操作:

     

    1.  GC為所有可遍歷的對象建一張圖。在上面的例子中,圖包含對象B,C,E,G。

    2.  GC掃描短弱引用表。如果表中指針指向的對象不在圖中,那么這個指針標識的是一個不可遍歷的對象,短弱引用表中的這個位置置為null。在上面的例子中,對象D的位置置為null,因為它不是圖的一部分。

    3.  GC掃描Finalization隊列。如果隊列中的指針所指的對象不在圖中,那么這個指針標識一個不可遍歷的對象,指針從Finalization隊列中移到FReachable隊列中。這時,對象被認為是可遍歷的,所以加到圖中。在上面的例子中,對象A,D,F是不包含在圖中但看作是可遍歷的對象,因為它們屬于Finalization隊列。進而Finalization隊列被清空。

    4.  GC掃描長弱引用表。如果表中的指針指的對象不在圖中(現在圖包括FReachable隊列中指針所指的對象),那么指針標識一個不可遍歷的對象,所在位置置為null。由于對象CF都包含在圖中,都不置null。

    5.  GC整理(Compact)內存,擠出不可遍歷對象留下的空隙。在上面的例子中,對象H是唯一從堆中刪除的對象,它所分配的內存被收回。

     

    代(Generations

           由于垃圾回收要在停止整個程序的情況下才能完成,它們可能會在程序執行期間進行任意長時間的中斷。GC也有可能中斷為滿足實時系統的需求而要求及時響應的事件。

     

           GC中有一個特征叫代(Generations),就是專門為提高性能而設計的。一個多代的GC是通過對觀察用各種語言編寫的大部分程序而得到兩個事實進行仔細分析而得到的:

     

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: net 中的 垃圾 回收


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>