python,.Net,Java的垃圾回收機制
華電北風吹
天津大學計算機學院
日期:2016-08-26
一、python的垃圾回收機制
1、引用計數
當一個物件的引用被建立或者複製時,物件的引用計數加1;當一個物件的引用被銷燬時,物件的引用計數減1;當物件的引用計數減少為0時,就意味著物件已經沒有被任何人使用了,可以將其所佔用的記憶體釋放了。
2、分代回收
將系統中的所有記憶體塊根據其存活時間劃分為不同的集合,每一個集合就成為一個“代”,垃圾收集的頻率隨著“代”的存活時間的增大而減小。也就是說,活得越長的物件,就越不可能是垃圾,就應該減少對它的垃圾收集頻率。那麼如何來衡量這個存活時間:通常是利用幾次垃圾收集動作來衡量,如果一個物件經過的垃圾收集次數越多,可以得出:該物件存活時間就越長
二、.Net垃圾回收機制
在.NET的GC把所有託管堆內的物件按照其已經不再被使用的可能性分為三類,並且從最有可能不被使用的類別開始掃描,.NET對這樣的分類類別有一個稱呼:代(Generation)。GC會把所有的託管堆內的物件分為0代、1代和2代:
第0代,新近分配在堆上的物件,從來沒有被垃圾收集過。任何一個新物件,當它第一次被分配在託管堆上時,就是第0代。
第1代,經歷過一次垃圾回收後,依然保留在堆上的物件。
第2代,經歷過兩次或以上垃圾回收後,依然保留在堆上的物件。如果第2代物件在進行完垃圾回收後空間仍然不夠用,則會丟擲OutOfMemoryException異常。
對於這三代,我們需要知道的是並不是每次垃圾回收都會同時回收3個代的所有物件,越小的代擁有著越多被釋放的機會。
CLR對於代的基本演算法是:每執行N次0代的回收,才會執行一次1代的回收,而每執行N次1代的回收,才會執行一次2代的回收。當某個物件例項在GC執行時被發現仍然在被使用,它將被移動到下一個代上。
三、Java垃圾回收機制
當垃圾回收啟動時,Java程式暫停執行。JVM從根出發,找到可到達物件,將可到達物件複製到空白區域中並緊密排列,修改由於物件移動所造成的引用地址的變化。最後,直接清空物件原先存活的整個區域,使其成為新的空白區域。
1、JVM中的堆
堆分為三代——永久世代(permanent generation)、年輕世代(young generation)和成熟世代(tenured generation)。
其中的永久世代(permanent generation)中存活的是Class物件。這些物件不會被垃圾回收。年輕世代(young generation)和成熟世代(tenured generation)需要進行垃圾回收。年輕世代中的物件世代較近,而成熟世代中的物件世代較久。
其中,年輕世代進一步分為三個區域——eden(伊甸)、from和to。eden(伊甸): 新生物件存活於該區域。新生物件指從上次GC後新建的物件。from, to: 這兩個區域大小相等,相當於copy and sweep中的兩個區域。當新建物件無法放入eden區時,將出發minor collection。JVM採用copy and sweep的策略,將eden區與from區的可到達物件複製到to區。經過一次垃圾回收,eden區和from區清空,to區中則緊密的存放著存活物件。隨後,from區成為新的to區, to區成為新的from區。如果進行minor collection的時候,發現to區放不下,則將部分物件放入成熟世代。另一方面,即使to區沒有滿,JVM依然會移動世代足夠久遠的物件到成熟世代。如果成熟世代放滿物件,無法移入新的物件,那麼將觸發major collection。JVM採用mark and sweep的策略,對成熟世代進行垃圾回收。