8.java回收機制

概念

Java的垃圾回收機制是Java虛擬機提供的能力,用於在空閒時間以不定時的方式動態回收無任何引用的對象佔據的內存空間。我們用System.gc()或者
Runtime.getRuntime().gc()  來通知垃圾回收機(JVM)回收垃圾。很多人說垃圾回收回收的是沒有用的對象,這裏不準確的。

垃圾回收的作用

 1,定期發現那些對象不再被引用,並把這些對象佔據的堆空間釋放出來。

 2,垃圾收集器還需要處理由於對象動態生成與銷燬產生的堆碎塊,以便更有效的利用虛擬機內存。

區分什麼是垃圾(活動與垃圾的區分)

引用計數法

       堆中每一個對象都有一個引用計數。當新創建一個對象,或者有變量被賦值爲這個對象的引用,則這個對象的引用計數加1;當一個對象的引用超過生存期或者被設置一個新的值時,這個對象的引用計數減1。當對象的引用計數變爲0時,就可以被當作垃圾收集。
         這種方法的好處是垃圾收集較快,適用於實時環境。缺點是這種方法無法監測出循環引用。例如對象A引用對象B,對象B也引用對象A,則這兩個對象可能無法被垃圾收集器收集。因此這種方法是垃圾收集的早期策略,現在很少使用。

跟蹤法

     這種方法把每個對象看作圖中一個節點,對象之間的引用關係爲圖中各節點的鄰接關係。垃圾收集器從一個或數個根結點遍歷對象圖,如果有些對象節點永遠無法到達,則這個對象可以被當作垃圾回收。
     容易發現,這種方法可以檢測出循環引用,避免了引用計數法的缺點,較爲常用。

常用的垃圾回收方法

標記-清除收集器

      這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。

標記-壓縮收集器

    有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象複製到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。

複製收集器

     這種收集器將堆棧分爲兩個域,常稱爲半空間。每次僅使用一半的空間,虛擬機生成的新對象則放在另一半空間中。垃圾回收器運行時,它把可到達對象複製到另一半空間,沒有被複制的的對象都是不可達對象,可以被回收。這種方法適用於短生存期的對象,持續複製長生存期的對象由於多次拷貝,導致效率降低。缺點是隻有一半的虛擬機空間得到使用。

增量收集器

   增量收集器把堆棧分爲多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。

分代收集器

    這種收集器把堆棧分爲兩個或多個域,用以存放不同壽命的對象。虛擬機生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的算法以優化性能。這樣可以減少複製對象的時間。

併發收集器

       併發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因爲其他應用程序可進行其他的後臺操作,所以中斷其他處理的實際時間大大降低。

並行收集器

       併發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因爲其他應用程序可進行其他的後臺操作,所以中斷其他處理的實際時間大大降低。

自適應收集器

 根據程序運行狀況以及堆的使用狀況,自動選一種合適的垃圾回收算法。這樣可以不侷限與一種垃圾回收算法。


這裏要說到一個垃圾算法上的實現,火車算法

垃圾收集算法一個很大的缺點就是難以控制垃圾回收所佔用的CPU時間,以及何時需要進行垃圾回收。火車算法是分代收集器所用的算法,目的是在成熟對象空間中提供限定時間的漸進收集。目前應用於SUN公司的Hotspot虛擬機上。

              在火車算法中,內存被分爲塊,多個塊組成一個集合。爲了形象化,一節車廂代表一個塊,一列火車代表一個集合,見圖一

 

圖一

注意每個車廂大小相等,但每個火車包含的車廂數不一定相等。垃圾收集以車廂爲單位,收集順序依次爲1.11.21.31.42.12.22.33.13.23.3。這個順序也是塊被創建的先後順序。

垃圾收集器先從塊1.1開始掃描直到1.4,如果火車1四個塊中的所有對象沒有被火車2和火車3的對象引用,而只有火車1內部的對象相互引用,則整個火車1都是垃圾,可以被回收。

圖二,車廂1.1中有對象A和對象B1.3中有對象C1.4中有對象D車廂2.2中有對象E,車廂3.3中有對象F。在火車1中,對象C引用對象A,對象B引用對象D,可見,火車2和火車3沒有引用火車1的對象,則整個火車1都是垃圾。

 

圖二

如果火車1中有對象被其它火車引用,見圖三,掃描車廂1.1時發現對象A被火車2中的E引用,則將對象A從車廂1.1轉移到車廂2.2,然後掃描A引用的對象D,把D也轉移到車廂2.2,然後掃描D,看D是否引用其它對象,如果引用了其它對象則也要轉移,依次類推。掃描完火車1的所有對象後,剩下的沒有轉移的對象都是垃圾,可以把整個火車1都作爲垃圾回收。注意如果在轉移時,如果車廂2.2空間滿了,則要在火車2末尾開闢新的車廂2.4,將新轉移的對象都放到2.4,即火車的尾部)

 

圖三

     補充說明:垃圾回收器一次只掃描一個車廂。圖三中的對象B與C並不是立即被回收,而是先會被轉移到火車1的尾部車廂。即掃描完1.1後,B被轉移到火車1尾部,掃描完1.3後,C被轉移到車尾。等垃圾收集器掃描到火車1尾部時,如果仍然沒有外部對象引用它們,則B和C會被收集。

     火車算法最大的好處是它可以保證大的循環結構可以被完全收集,因爲成爲垃圾的循環結構中的對象,無論多大,都會被移入同一列火車,最終一起被收集。還有一個好處是這種算法在大多數情況下可以保證一次垃圾收集所耗時間在一定限度之內,因爲一次垃圾回收只收集一個車廂,而車廂的大小是有限度的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章