垃圾回收機制html
1、引用計數java
特色:jvm
簡單,速度慢orm
原理:htm
每一個對象都含有一個引用計數器,當有引用鏈接值對象是,引用計數加1.當引用離開做用域或被置爲null時,引用計數減1.雖然管理引用計數的開銷不大,但這項開銷在整個程序生命週期中將持續發生。垃圾回收器會在含有所有對象的遍歷表上遍歷,當發現某個對象的引用計數爲0時,就釋放其佔用的空間。可是,引用計數模式常常會在計數值變爲0時當即釋放對象。這種方法還有個缺陷,若是對象之間存在循環引用,可能會出現對象應該被回收,但引用計數卻不爲0的狀況。對垃圾回收器而言,定位這樣的的交互自引用的對象組所需的工做量極大。對象
評價:blog
這種方式經常使用來講明垃圾收集的工做方式,但彷佛從未被應用於java虛擬機實現中。生命週期
2、遍歷全部的引用進程
思想:內存
對任何活的對象,必定能最終追溯到器存活在堆棧或靜態存儲區之中的引用。這個引用鏈條可能會產國數個對象層次,由此,若是從堆棧和靜態存儲區開始,遍歷全部的的引用,就能找到全部活的對象。這種方式解決了交互自引用的對象組的問題。
這種方式下java虛擬機將此採用一種自適應的垃圾回收技術。至於如何處理找到的存活對象,取決於不一樣的實現。
中止-複製
先暫停程序的運行(因此它不屬於後臺回收模式),而後將全部存活的對象從當前堆複製到另外一個堆,沒有被複制的所有都是垃圾。當對象被複制到新堆時,它們是一個挨着一個的,因此新堆保持緊湊排列,而後就能夠按前述方法簡單直接的分配新空間了。
評價:
這種所謂的複製式回收器,效率會下降,兩個緣由。
首先,得有兩個堆,而後在兩個分離的堆之間來回倒騰,從而得維護比實際須要多一倍的空間。某些java虛擬機對此問題的處理方式是,按需從堆中分配幾塊較大的內存,複製動做發生在這些大塊內存之間。
第二個問題在於複製,程序進入穩定狀態以後,可能只會產生少許垃圾,甚至沒有垃圾。儘管如此,複製式回收器仍然會將全部內存自一處複製到另外一處,這很浪費。爲了不這種情形,一些java虛擬機會進行檢查:要是沒有新垃圾產生,就會轉換到另外一種工做模式(即:自適應)。這種模式成爲標記-清掃,sun公司早期的java虛擬機使用了這種技術。對通常用途而言,標記-清掃方式速度至關慢,可是當你知道只會產生少許垃圾甚至不會產生垃圾時,它的速度就很快了。
標記-清掃
思路一樣是從堆棧和靜態存儲區出發,遍歷全部的引用,進而找出全部存活的對象。每當它找到一個存活的對象,它就會給對象設一個標記,這個過程當中不會回收任何對象。只有所有標記工做完成的時候,清理動做纔會開始。在清理過程當中,沒有標記的對象將被釋放,不會發生任何複製動做。因此剩下的空間是不連續的,垃圾回收器要是但願獲得連續空間的話,就得從新整理剩下的對象。
3、綜述
「中止-複製」的意思是這種垃圾回收動做不是在後臺進行的;相反,垃圾回收動做發生的同時,程序將會被暫停。在sun公司的文檔中會發現,許多參考文獻將垃圾回收視爲低優先級的後臺進程,但事實上垃圾回收器在sun公司早期版本的java虛擬機中並不是以這種方式實現的。當可用內存數量較低時,sun版本的垃圾回收器會暫停運行程序,一樣,「標記-清掃」工做也必須在程序暫停的狀況下才能進行。
如前文所述,在這裏所討論的java虛擬機中,內存分配以較大的「塊」爲單位。若是對象較大,它會佔用單獨的塊。嚴格來講,「中止-複製」要求在釋放舊有對象以前,必須先把全部存活對象從舊堆複製到新堆,這將致使大量內存複製行爲。有了塊以後,垃圾回收器在回收的時候就能夠往廢棄的塊裏拷貝對象了。每一個塊都用相應的「代數」來記錄他是否還存活。一般,若是塊在某處被引用,其「代數」會增長;垃圾回收器將對上次回收動做以後新分配的塊進行整理。這對處理大量短命的臨時對象頗有幫助。垃圾回收器會按期進行完整的清理動做——大型對象仍然不會被複制(只是其代數會增長),內含小型對象的塊則被複制並整理。java虛擬機會進行監視,若是全部對象都很穩定,垃圾回收器的效率下降的話,就切換到「標記-清掃」方式;一樣java虛擬機會跟蹤「標記-清掃」的效果,要是對空間出現不少碎片,就會切換回「中止-複製」方式。這就是「自適應」技術。(自適應的、分代的、中止-複製、標記-清掃式垃圾回收器)
4、其餘文章
看了一篇講解詳細的文章,與上面寫的機制可以對應起來,能夠看一下,可以清楚經常使用的jvm的詳細的各類垃圾回收方式。http://www.cnblogs.com/zhguang/p/3257367.html#commentform