垃圾回收

                             垃圾回收

JAVA的對內存是一個運行時數據區,用以保存類的實例(對象),JAVA虛擬機的內存中存儲着正在運行的應用程序建立所建立的所有對象,這些對象不需要程序通過代碼來顯示釋放。一般來說,堆內存的回收由垃圾回收來負責,所有JVM實現都有一個由垃圾回收器管理的堆內存。垃圾回收是一種動態存儲管理技術,它自動釋放不再被程序引用的對象,按照特定的垃圾回收算法來實現內存資源的自動回收功能。

    

說到垃圾回收(Garbage Collection,GC),很多人就會自然而然地把它和Java聯繫起來。在Java中,程序員不需要去關心內存動態分配和垃圾回收的問題,這一切都交給了JVM來處理。顧名思義,垃圾回收就是釋放垃圾佔用的空間,那麼在Java中,什麼樣的對象會被認定爲垃圾那麼當一些對象被確定爲垃圾之後,採用什麼樣的策略來進行回收(釋放空間)?在目前的商業虛擬機中,有哪些典型的垃圾收集器?

垃圾回收機制

一. 垃圾回收的特點:

1.      垃圾回收機制的工作目標是回收無用對象的內存空間,這些內存空間是JVM堆內存的內存空間,垃圾回收只能回收內存資源,對於其他的物理資源如:數據庫連接,硬盤I/O等資源則是無效的。

2.      爲了讓垃圾回收機制回收那些不再使用的對象,可以將引用變量設置爲null,通過這種方式告訴垃圾回收機制可以回收該對象。

3.      垃圾回收發生的不可預知性。不同的JVM採用了不同的垃圾回收機制和不同的垃圾算法,因此它可能是定時發生,也有可能當CPU空閒時發生,也有可能和原始的垃圾回收機制相同,當內存出現極限時發生,我們可以通過調用Runtime對象的gc()和System.gc()

建議系統進行垃圾回收,這種方式依然不能精確的控制垃圾回收機制的執行。

4.      準確性主要包括兩個方面:一是垃圾回收機制能夠精確的標記活着的對象;二是垃圾回收器能夠精確的定位對象之間的引用關係。前者是完全回收所有廢棄對象的前提,否則就可能出現內存的泄露;後者實現歸併和複製的必要條件,通過這種方法可以保證所有對象都被可靠的回收,所有對象都能背後從新分配,從而減少內存碎片的產生。

5.      現在JVM有多種的不同垃圾回收實現。

 

二.如何確定某個對象是“圾”?

一.GC執行條件

JVM進行次GC的頻率很高,但因爲這種GC佔用時間極短,所以對系統產生的影響不大。更值得關注的是主GC的觸發條件,因爲它對系統影響很明顯。總的來說,有兩個條件會觸發GC

   1.當沒有引用變量指向原先分配給某個對象的內存時,該內存便成爲垃圾,JVM的一個超級線程會自動釋放該內存區。垃圾回收意味着程序不再需要的對象是“垃圾信息”,這個信息將被丟棄。

       2.Java堆內存不足時,GC會被調用。當應用線程在運行,並在運行過程中創建新對象,若這時內存空間不足,JVM就會強制地調用GC線程,以便回收內存用於新的分配。若GC一次之後仍不能滿足內存分配的要求,JVM會再進行兩次GC作進一步的嘗試,若仍無法滿足要求,則 JVM將報“out of memory”的錯誤,Java應用將停止。

強制系統垃圾回收的兩種方式:

1.      調用System類的gc()靜態方法:System.gc().

2.      調用Runtime對象的gc()實例方法:Runtime.getRuntime().gc()。

Finaliza()方法具有如下4種特點。

1.      永遠不會主動調用某個對象的finalize()方法,該方法應交給垃圾回收機制調用。

2.      Finalize()方法何時被調用,是否被調用具有不確定性,不要把finalize()方法當成一定會被執行的方法。

3.      當JVM執行可恢復對象的finalize()方法時,可能使該對象或系統中其他對象重新回到可達狀態。

4.      當JVM執行finalize()方法出現異常時,垃圾回收機制不會報告異常,程序繼續執行。

 

 

 

二.Java 中有不同的引用類型。判斷實例是否符合垃圾收集的條件都依賴於它的引用類型。

 

引用類型

垃圾收集

強引用(Strong Reference

不符合垃圾收集

軟引用(Soft Reference

垃圾收集可能會執行,但會作爲最後的選擇

弱引用(Weak Reference

符合垃圾收集

虛引用(Phantom Reference

符合垃圾收集

強引用:這是java程序中最常見的應用類型。程序創建一個對象,並把這個對象賦給一個引用變量,程序通過該引用變量來操作實際的對象,當一個對象被一個或多個的引用變量所引用時,它處於可達狀態,不可能被系統垃圾回收機制回收。

軟引用:

 

 

 

 

三.典型的垃圾收集算法

一.引用技術算法

       在java中是通過引用來和對象進行關聯的,也就是說如果要操作對象,必須通過引用來進行。那麼很顯然一個簡單的辦法就是通過引用計數來判斷一個對象是否可以被回收。不失一般性,如果一個對象沒有任何引用與之關聯,則說明該對象基本不太可能在其他地方被使用到,那麼這個對象就成爲可被回收的對象了。這種方式成爲引用計數法。

這種方式的特點是實現簡單,而且效率較高,但是它無法解決循環引用的問題,因此在Java中並沒有採用這種方式(Python採用的是引用計數法)。看下面這段代碼:

 


 

最後面兩句將object1和object2賦值爲null,也就是說object1和object2指向的對象已經不可能再被訪問,但是由於它們互相引用對方,導致它們的引用計數都不爲0,那麼垃圾收集器就永遠不會回收它們。

二.可達性分析算法

這個算法的基本思路就是通過一系列的稱謂“GC Roots"的對象作爲起始點,從這些節點開始向下搜索,搜索所有走過的路徑爲引用鏈,當一個對象到GC Roots沒有任何引用鏈項鍊時,則證明此對象時不可用的

 

上面的這張圖,對象object5、object6、object7雖然互相沒有關聯,但是它們到GC Roots是不可達的,所以它們將會被判定爲是可回收的對象

 

四.典型的垃圾收集器

1.每一個對象都有一個finalize方法,這個方法是從Object類繼承來的。

2.每一個對象只能調用finalize方法一次。如果在finalize方法執行時產生異常(exception),則該對象仁可以被垃圾回收集器收集。

3.finalize方法可以被重載,但是又具備初始的finalize方法特點的。

4.finalize方法可以明確地被調用,但它卻不能進行垃圾收集

5.垃圾收集不可以被強制執行,但程序員可以通過調用System.gc方法來建儀執行垃圾收集器

 

發佈了31 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章