垃圾回收
內存管理(Memory Management)
內存管理指的是用戶為變量在heap(堆積/堆)上分配內存後,誰來管理釋放的問題
內存釋放
- 程式員手動管理(
C,C++) - 語言運行時自動管理(
C#,Java,Python,JS)
當我們
new一個對象的時候,會在heap內存上畫出了這麼一塊內存空間,然後在這裡面放上去當前這個class所需要的成員變量,然後將這塊內存的地址,給到了stack(堆疊/棧)內存上的一個「引用類型的變量」,那個變量就是我們在程式寫的那個對象/物件。
當一個方法壓入
stack(堆疊/棧)內存的時候,這個方法裡面分配的簡單的的變量,例如一個小int,一個小float,會隨著方法的完成,在stack(堆疊/棧)內存隨著方法直接消失。
托管資源
- 托管資源是
.Net平台CLR提供的內存管理方法,由.Net負責內存生成及釋放 - 托管資源
Stack(堆疊/棧)資源:根據函數運行自動分配釋放- 托管
Heap(塊積/堆):用戶需要的時候new,不需要會自動釋放
非托管資源
CLR系統只能跟蹤其生存周其,而不能決定如何數放資源;如資料庫連接、文件句柄(file handle)及指針結果等
垃圾收集(Garbage Collection)
- 垃圾收集即通過一定算法,得到內存中哪些對象需要被回收,並在
GC階段將垃圾對象回收的過程 從程序的根對象(Root)開始層層遍歷在
Heap(堆積/堆)上分配的對象,不再被引用到的對象即判定垃圾;可被引用到的對象稱為Reachable Object- Root
- 全局對象 (長期存在)(例如:單例模式)
- 靜態變量 (長期存在)
Stack(堆疊/棧)上現存變量CPU寄存器中變量
上兩個是:長期存在的,下兩個是:此時此刻我們是需要他們的
舉例
當執行完 showMe()方法後,在Stack內存的p1變量就會隨著方法消失
假設CLR現在要判斷一輪,剛好到達了他這個內存回收,垃圾回收時間點,它會看當前哪些內存該被回收,那很明顯了,p1變量消失了,那原來被p1所引這塊Heap內存(name,arr)是不是就變成需要被回收清理的內存呀
事還沒完呢,p1對象裡面還有name,arr這兩個變量所引用的這兩塊內存是誰呀?carma, 123,這兩塊是不是就變成無家可歸了,你會發現Stack上和Heap上都沒有任何的對象去引用這兩個塊內存了,所以也要消失了。
Mark-Compact標記壓縮算法
MC算法是C#採用的垃圾回收算單,具體分為兩個階段,即Mark與Compact階段1:標記清除階段(
Mark-Sweep) 假設所有對象都可回收,找出不能回收對象,打上標記階段2:壓縮階段(
Compact) 移動不連續內存,從Heap基址開始排列
地址修複
Compact過程中,程動了Heap當中的對象,對象地發生變化,需要修複引用對象的Stack上變量、CPU寄存器變量及Heap上其他引用
總結
C#採用CLR提供的托管內存辦法,利用GC來處理內存回收GC從Root對象開始遍歷,將對象分為:可達(Reachable)與不可達(Unreachable)GC採用Mark-Compact標記壓縮算法- 內存
Compact會觸發引用地址修復








