1. 程式人生 > >Java垃圾回收原理(2)

Java垃圾回收原理(2)

垃圾回收

Java虛擬機采用一種自適應的垃圾回收技術。依據的思想:對任何“活”的對象,一定能最終追溯到其存活在堆棧或靜態存儲區之中的引用。這個引用鏈條可能會穿過數個對象層次。由此,如果從堆棧和靜態存儲區開始,遍歷所有的引用,就能找到所有活的對象。對於發現的每個引用,必須追蹤它所引用的對象,然後是此對象所包含的所有的引用,如此反復進行,直到“根源於堆棧和靜態存儲區的引用”所形成的網絡全部被訪問為止。至於如何處理找到存活的對象,取決於不同的Java虛擬機的實現。有一種名為停止-復制。顯然這意味著,先暫停程序的運行,然後將所有存活的對象從當前堆復制到裏一個堆,沒有被復制的全部都是垃圾。當對象被復制到新堆時,它們是一個挨著一個,所以新堆保持緊湊排列,然後就可以按前述方法簡單、直接地分配空間了。

當然這種所謂“復制式回收器”,效率會降低。為了避免這種情況,一些Java虛擬機會進行檢查:要是沒有新垃圾產生,就會轉換到另一種工作模式。這種模式稱為標記-清掃。這個方式速度會很慢,但是當只會產生少量的垃圾甚至不會產生垃圾時,她得速度就很快了。

“標記-清掃”所依據的思路同樣是從堆棧和靜態存儲區出發,遍歷所有的引用,進而找出所有存活的對象。每當它找到一個對象,就會給對象設一個標記,這個過程中不會回收任何對象。只有全部標記工作完成的時候,清理動作才會開始。在清理過程中,沒有標記的對象將被釋放,不會發生復制動作。所以剩下的堆空間是不連續的,垃圾回收器要是希望得到連續的空間的話,就得重新整理剩下的對象。

如前文所述,在這裏所討論的Java虛擬機中,內存分配以比較大的“塊”為單位。如果對象比較大,它會占用單獨的塊。嚴格來說,停止-復制要求在釋放舊的對象之前,必須先把所有存活對象從舊堆復制到新堆,這將導致大量內存復制行為。有了“塊”之後,垃圾回收器在回收的時候就可以往廢棄的塊裏拷貝對象了。每個快都用相應的代數來記錄它是否還存活。通常,如果快在某處被引用,其代數會增加;垃圾回收器將對上次回收動作之後新分配的快進行整理。這對處理大量短命的臨時對象很有幫助。垃圾回收器會定期進行完整的清理動作--大型對象仍然不會被復制(只是其代數會增加),內含小型對象的那些快則被復制並整理。Java虛擬機會進行監視,如果所有對象都很穩定,垃圾回收器的效率降低的話,就會切換到標記-清掃方式;同樣,Java虛擬機會跟蹤標記-清掃的效果,要是堆空間出現很多碎片,就會切換回停止-復制方式。這就是“自適應”技術。


Java垃圾回收原理(2)