1. 程式人生 > >CLR VIA C# 閱讀筆記和感悟(二)

CLR VIA C# 閱讀筆記和感悟(二)

GC垃圾回收:垃圾回收機制其實是對記憶體的碎片化管理,首先會暫停所有執行緒的執行,防止碎片化管理時,物件的狀態被修改,然後遍歷託管堆中的所有物件,刪除沒有變數引用的物件,並且移動堆中的所有物件的記憶體地址,刪除物件之間的空隙,變成一塊連續的記憶體,提高物件的引用效率,節省更多的記憶體空間,但這會導致之前變數儲存的地址失效,因為之前儲存的地址不再是是物件的起始地址了,所以CLR會根據堆中物件移動的偏移量修改之前變數儲存的地址,使得變數儲存的地址和物件的真實地址一致,然後恢復所有執行緒。

        垃圾回收採用了"代"的管理機制,第0代物件最容易被垃圾回收,第1代物件是在第0代物件清理中存活下來的物件,第2代物件保留的是第1代物件清理中存活下來的物件,其中第0代物件的清理最頻繁,第2代物件的清理最慢,因為垃圾回收機制都是從第0代開始清理的。









        CLR會對託管堆進行3代的記憶體分配,只要記憶體使用查過預期就會執行垃圾回收,而過載了object型別Finalize方法的物件,在被標記為第0代物件後,本應是垃圾的它因為需要被執行Finalize過載而被引用到內部的一個終結器列表中,由此物件再次被引用,從而物件被複活了,並儲存在第1代中,Finalize方法執行完後就再也沒有誰引用它,所以第1代中執行垃圾回收時就會刪除這個物件。借用書中的圖來直觀感受下:


AppDomain:程式啟動後會告訴系統建立一個程序,程序中會包含程序一開始就會建立的AppDomain程式集容器,容器中包含了程式集中的各種類資訊,也就是說我們的程式碼在執行時都是在AppDomain這個大環境中定義好,執行時交給CLR處理,程式碼執行到哪裡CLR中的JIT編譯器就動態編譯到哪裡,並把編譯後的CPU指令快取在記憶體中,然後以後的每次執行都是獲取已快取的CPU指令並交給CPU執行。這裡給我的感覺是,本地軟體exe執行時是把軟體本身執行在記憶體中嗎?其實不是的,軟體執行只是系統建立一個程序的契機,系統只是把軟體執行的必要資訊讀取到記憶體中,並動態編譯執行而已,但一些附加二進位制檔案會被載入到記憶體中,比如音訊圖片等。一個程序可以包含有多個程式集容器,程式集容器之間是隔離的,不會對資料造成損壞。借用下書中的一張圖來直觀感受下:




版權宣告:本文為博主原創文章~轉載請註明出處