從本篇文章開始,將開始一個新的系列JVM。JVM是一個很是龐大且複製的技術體系,可是對於程序猿的升級,走向更高階所必要經歷的,曾經也下決心要好好學習一番,然而毅力不足都中途放棄。算法
GC的做用就是回收垃圾,可是要作到作點必需要解決兩個問題:性能
這兩個問題可謂是GC的核心,本篇文章將從算法角度學習GC是怎樣解決這兩個問題。學習
在Java應用中,可被回收的對象必然是無用對象,即沒有其餘對象引用它或者其脫離了應用的中的對象總體:線程
如上圖,藍色標記的對象之間相互引用,都是存活對象,GC不該該回收。而紅色標記的對象,已經沒有任何對象引用它,GC應該回收它。3d
從以上能夠肯定,GC首先應該回收沒有任何引用指向其的對象。如何表達沒有任何引用?code
爲每一個對象維護一個計數器,該計數器表示指向其的引用。當沒有引用其時,則計數器應該爲0,GC則應該回收。這種算法被稱爲引用計數法。對象
如上圖,當計數器爲0時,表示該對象已經沒有任何引用,可被垃圾收集器回收。該算法實現很是簡單,且性能較佳,可是存在侷限性。blog
引用計數法當然簡單易於理解,可是它沒法解決相互引用的問題。當兩個以上的對象之間相互引用,可是它們已經脫離整個Java對象的總體時,引用計數法便沒法表達出它們是可回收對象:內存
如上圖,當兩個紅色的標記的對象相互引用,此外沒有任何對象引用它們,顯然它們是可回收對象。可是引用計數法會形成沒法被回收。資源
假若有如下代碼:
void referenceCount() { ... A a = new A(); B b = new B(a); a.setB(b); ... }
A和B之間相互引用,可是此外沒有任何對象引用A和B,那麼當線程運行退出referenceCount方法時,A和B依然不能被回收。
因爲引用計數法的侷限性,顯然它不適合做爲JVM中定位可回收對象的算法。實際上再JVM中使用另外一種方式表示對象是否可回收 — 可達性分析算法。
可達性分析算法:能從GC Roots找到一條到該對象的引用鏈路,則該對象就是存活對象,如何找不到,則該對象就是可回收對象。
這裏首先要明白什麼是GC Roots:
Note:
簡而言之,可達性分析算法就是根搜索算法,相似於樹結構的搜索。其中GC Roots就是根,其餘對象就是樹上的節點。在根和節點之間尋找路徑。
從圖中能夠看出,可達性分析算法可以解決相互引用的問題。從GC Roots開始到對象之間存在一條引用鏈路,則就是存活對象,反之便是死亡對象。
經過以上的可達性分析算法,GC可以找到堆區中的可回收對象,可是具體怎樣回收才能具備更高的效率呢?在JVM中存在如下幾種回收算法:
以上三種算法都各有利弊,下面逐一介紹。
顧名思義,該算法分爲兩個階段,先標記出可回收對象,而後再清除這些對象。
將堆區當作以上連輸的方塊片斷,紅色表明沒有GC Roots引用的對象,藍色表明有引用。
標記清除算法,首先針對堆區對象進行標記,標記出沒有GC Root是對象引用的對象。而後再將沒有GC Roots引用的對象清除。
該算法的效率較高,只須要標記而後清除便可。可是從圖中也能夠看出問題所在,在清除後,會形成大量的不連續的內存碎片,當有大對象分配時,將又會觸發GC,從而影響性能。
爲了解決標記清除算法的致使的內存碎片問題,複製算法所以而生。複製算法的思想是將內存分爲兩塊,每次只使用其中一塊,回收時將存活的對象複製到另外一塊中,而後將使用的那塊徹底清除,再使用新的複製那塊。
通過複製算法後,不會再產生斷斷續續的內存碎片。每次垃圾回收以後,都能獲得連續的大片內存。可是又產生了新的問題,內存是昂貴資源,將其分紅兩塊,每次只使用其中一塊,形成了資源浪費。可是實際中,對象基本上都是朝生夕死,能存活的對象少之又少,因此實際中通常不會按照1:1的比例分塊。在Hostspot的年輕代默認按照8:1的進行劃分,即Eden:Survivor=8:1。
爲了既解決標記清除算法帶來的內存碎片問題,又能很好解決複製算法的內存犧牲問題。又出現標記整理算法。它相似標記清除,可是又增長了一個整理過程。即將存活對象往一端移動,整理內存碎片,造成連續內存。
經過標記清理,可以將回收垃圾對象,釋放內存。經過整理壓縮,可以造成連續內存,解決內存碎片。
雖然標記整理算法解決了複製算法和標記清除算法帶來的問題,可是整理壓縮也是耗費性能,下降效率。
以上的GC回收算法都各有利弊,實際使用中,根據內存區域的劃分以及其特色,HotSpot不單一採用以上的算法,而是根據堆區不一樣分代,分別採用以上算法,這種算法被稱爲分代算法。
因爲Java對象具備朝生夕死的特色,堆區通常劃分爲新生代(年輕代)和老年代(年老代)。新生代對象生存週期短暫,老年代對象生成周期較長:
本篇文章主要介紹GC中兩個核心問題,第一:GC如何肯定哪些對象是可回收的,在HotSpot中使用從GC Roots開始的可達性分析算法,定位對象是否存活。第二:在肯定對象的存活與否後,採用何種策略回收對象。商業虛擬機中多數採用分代算法解決該問題。在瞭解了GC回收算法後,下篇文章再圍繞這些算法學習HotSpot中的有哪些具體實現。