Java的垃圾回收機制

orchid發表於2013-09-17

關於java的垃圾回收機制,網上的牛文一堆。我寫這個文章,只是我對這個問題的一點理解,看完這些牛文之後的一點點總結。至於實際上JVM是不是這麼搞垃圾回收,這個確證起來還是比較複雜的。

首先,為什麼要垃圾回收?

因為記憶體有限,程式產生的一些垃圾必須清理,否則再大的記憶體也扛不住。C++這個語言賦予程式設計師對記憶體的使用權還比較多,開闢記憶體清理記憶體,都是程式設計師的事情。到了java,程式設計師貌似不需要太考慮記憶體的事情了,這些都有java虛擬機器接管了。java程式設計師只需要瞭解一些java到底怎麼回收記憶體的,但是不瞭解這個,對編寫好的java程式影響也不大吧(這個是我個人猜測,我只算個java初學者)。

第二,java怎麼找到那些記憶體已經變成了垃圾?

第一個方法,引用計數。這個似乎是個很古老的方法,現在JVM應該不用它了。引用計數就是記錄每個物件的引用它的次數,當這個引用次數變為0的時候,說明它沒用了,可以被清理走了。這個問題有什麼缺點呢?很明顯如果A引用了B,B引用了A,這種迴圈引用會帶來麻煩,因為A和B的引用次數永遠不會成為0,但是A和B可能都沒用了。

第二個方法,物件引用遍歷。物件引用遍歷從一組物件開始,沿著整個物件圖上的每條連結,遞迴確定可到達(reachable)的物件。如果某物件不能從這些根物件的一個(至少一個)到達,則將它作為垃圾收集。在物件遍歷階段,GC必須記住哪些物件可以到達,以便刪除不可到達的物件,這稱為標記(marking)物件。

第三,找到垃圾了之後,怎麼處理?

放著不管肯定是不行的,因為這涉及到JVM分配記憶體的問題。Java在堆中分配物件,在一些語言中,在堆上分配物件的代價十分高昂,但是,java不是這樣,java從堆分配空間的速度可以和其他語言從堆疊上分配空間的速度相媲美。Java能做到這個就和它的記憶體回收機制有關係。拿think in java的比喻,java中堆的實現像一個傳送帶,沒分配一個新物件,他就往前移動到一格。這個就必須保證記憶體的緊湊,不能出現太多的記憶體片段。所以JVM在回收垃圾的時候,必須做一些其他工作,保證這個緊湊性。

第一個方法:stop-and-copy。這種收集器將堆疊分為兩個域,常稱為半空間。每次僅使用一半的空間,JVM生成的新物件則放在另一半空間中。GC執行時,它把可到達物件複製到另一半空間,從而壓縮了堆疊。這種方法適用於短生存期的物件,持續複製長生存期的物件則導致效率降低。並且對於指定大小堆來說,需要兩倍大小的記憶體,因為任何時候都只使用其中的一半。注意,在執行這一操作的時候,要先暫停程式的執行。

第二個方法:mark-and-sweep.它依據的思路同樣是從堆疊和靜態儲存區出發,遍歷所有的引用,進而找到所有存活物件。每當它找到一個存活物件,就會給物件設一個標記,這個過程不會回收任何物件。只有全部標記工作完成的時候,清理動作才開始。在清理的過程中,沒有標記的物件將被釋放,不會發生任何複製動作。所以剩下的堆空間是不連續的,垃圾回收期要是希望得到連續空間的話,就得重新整理剩下的物件。mark-and-sweep也要在程式暫停的情況下才能進行。

三,增量收集器。增量收集器把堆疊分為多個域,每次僅從一個域收集垃圾,也可理解為把堆疊分成一小塊一小塊,每次僅對某一個塊進行垃圾收集。這會造成較小的應用程式中斷時間,使得使用者一般不能覺察到垃圾收集器正在工作。

四,分代收集器。複製收集器的缺點是:每次收集時,所有的標記物件都要被拷貝,從而導致一些生命週期很長的物件被來回拷貝多次,消耗大量的時間。而分代收集器則可解決這個問題,分代收集器把堆疊分為兩個或多個域,用以存放不同壽命的物件。JVM生成的新物件一般放在其中的某個域中。過一段時間,繼續存在的物件(非短命物件)將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的演算法以優化效能。

五,並行收集器。並行收集器使用某種傳統的演算法並使用多執行緒並行的執行它們的工作。在多CPU機器上使用多執行緒技術可以顯著的提高java應用程式的可擴充套件性

 

PS. 關於finalize()

這個方法在物件被垃圾回收時呼叫。因為垃圾回收這這事不太可控,因為只要記憶體夠用,可能JVM永遠不啟動垃圾回收,畢竟這個一個很耗時耗力的工作,所以,儘量少用finlaize()。這個終止器的用途類似於C++裡的解構函式,而且都是自動呼叫的。但是,兩者的呼叫時機不一樣,使兩者的表現行為有重大區別。C++的解構函式總是當物件離開作用域時被呼叫。這就是說,C++解構函式的呼叫時機是確定的,且是可被應用判知的。但是,Java終止器卻是在物件被銷燬時。由上所知,被丟棄的物件何時被銷燬,應用是無法獲知的。而且,對於大多數場合,被丟棄物件在應用終止後仍未銷燬。

相關文章