記得以前去平安面試的時候,面試官問到了垃圾回收,我當時也就是說說了垃圾回收的原理,可是具體有哪些實現策略,我當時是懵的。面試
概念:算法
Java的垃圾回收機制是Java虛擬機提供的能力,用於在空閒時間以不定時的方式動態回收無任何引用的對象佔據的內存空間。咱們用System.gc()或者
Runtime.getRuntime().gc() 來通知垃圾回收機(JVM)回收垃圾。不少人說垃圾回收回收的是沒有用的對象,這裏不許確的。併發
垃圾回收的做用:性能
1,按期發現那些對象再也不被引用,並把這些對象佔據的堆空間釋放出來。
優化
2,垃圾收集器還須要處理因爲對象動態生成與銷燬產生的堆碎塊,以便更有效的利用虛擬機內存。spa
區分什麼是垃圾(活動與垃圾的區分).net
引用計數法線程
堆中每個對象都有一個引用計數。當新建立一個對象,或者有變量被賦值爲這個對象的引用,則這個對象的引用計數加1;當一個對象的引用超過生存期或者被設置一個新的值時,這個對象的引用計數減1。當對象的引用計數變爲0時,就能夠被看成垃圾收集。
這種方法的好處是垃圾收集較快,適用於實時環境。缺點是這種方法沒法監測出循環引用。例如對象A引用對象B,對象B也引用對象A,則這兩個對象可能沒法被垃圾收集器收集。所以這種方法是垃圾收集的早期策略,如今不多使用。
對象
跟蹤法blog
這種方法把每一個對象看做圖中一個節點,對象之間的引用關係爲圖中各節點的鄰接關係。垃圾收集器從一個或數個根結點遍歷對象圖,若是有些對象節點永遠沒法到達,則這個對象能夠被看成垃圾回收。
容易發現,這種方法能夠檢測出循環引用,避免了引用計數法的缺點,較爲經常使用。
經常使用的垃圾回收方法
標記-清除收集器
這種收集器首先遍歷對象圖並標記可到達的對象,而後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器通常使用單線程工做並中止其餘操做。
標記-壓縮收集器
有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象複製到堆棧的新域中以便壓縮堆棧。這種收集器也中止其餘操做。
複製收集器
這種收集器將堆棧分爲兩個域,常稱爲半空間。每次僅使用一半的空間,虛擬機生成的新對象則放在另外一半空間中。垃圾回收器運行時,它把可到達對象複製到另外一半空間,沒有被複制的的對象都是不可達對象,能夠被回收。這種方法適用於短生存期的對象,持續複製長生存期的對象因爲屢次拷貝,致使效率下降。缺點是隻有一半的虛擬機空間獲得使用。
增量收集器
增量收集器把堆棧分爲多個域,每次僅從一個域收集垃圾。這會形成較小的應用程序中斷。
分代收集器
這種收集器把堆棧分爲兩個或多個域,用以存放不一樣壽命的對象。虛擬機生成的新對象通常放在其中的某個域中。過一段時間,繼續存在的對象將得到使用期並轉入更長壽命的域中。分代收集器對不一樣的域使用不一樣的算法以優化性能。這樣能夠減小複製對象的時間。
併發收集器
併發收集器與應用程序同時運行。這些收集器在某點上(好比壓縮時)通常都不得不中止其餘操做以完成特定的任務,可是由於其餘應用程序可進行其餘的後臺操做,因此中斷其餘處理的實際時間大大下降。
並行收集器
併發收集器與應用程序同時運行。這些收集器在某點上(好比壓縮時)通常都不得不中止其餘操做以完成特定的任務,可是由於其餘應用程序可進行其餘的後臺操做,因此中斷其餘處理的實際時間大大下降。
自適應收集器
根據程序運行情況以及堆的使用情況,自動選一種合適的垃圾回收算法。這樣能夠不侷限與一種垃圾回收算法。
這裏要說到一個垃圾算法上的實現,火車算法
垃圾收集算法一個很大的缺點就是難以控制垃圾回收所佔用的CPU時間,以及什麼時候須要進行垃圾回收。火車算法是分代收集器所用的算法,目的是在成熟對象空間中提供限定時間的漸進收集。目前應用於SUN公司的Hotspot虛擬機上。
在火車算法中,內存被分爲塊,多個塊組成一個集合。爲了形象化,一節車箱表明一個塊,一列火車表明一個集合,見圖一
圖一
注意每一個車箱大小相等,但每一個火車包含的車箱數不必定相等。垃圾收集以車箱爲單位,收集順序依次爲1.1,1.2,1.3,1.4,2.1,2.2,2.3,3.1,3.2,3.3。這個順序也是塊被建立的前後順序。
垃圾收集器先從塊1.1開始掃描直到1.4,若是火車1四個塊中的全部對象沒有被火車2和火車3的對象引用,而只有火車1內部的對象相互引用,則整個火車1都是垃圾,能夠被回收。
如圖二,車箱1.1中有對象A和對象B,1.3中有對象C,1.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會被收集。
火車算法最大的好處是它能夠保證大的循環結構能夠被徹底收集,由於成爲垃圾的循環結構中的對象,不管多大,都會被移入同一列火車,最終一塊兒被收集。還有一個好處是這種算法在大多數狀況下能夠保證一次垃圾收集所耗時間在必定限度以內,由於一次垃圾回收只收集一個車箱,而車箱的大小是有限度的。
本文同步分享在 博客「xiangzhihong8」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。