程序的運行必然須要申請內存資源,無效的對象資源若是不及時處理就會一直佔有內存資源,最終將致使內存溢出,因此對內存資源的管理是很是重要了。
爲了讓程序員更專一於代碼的實現,而不用過多的考慮內存釋放的問題,因此,在Java語言中,有了自動的垃圾回收機制,也就是咱們熟悉的GC。程序員
有了垃圾回收機制後,程序員只須要關心內存的申請便可,內存的釋放由系統自動識別完成。換句話說,自動的垃圾回收的算法就會變得很是重要了,若是由於算法的不合理,致使內存資源一直沒有釋放,一樣也可能會致使內存溢出的。算法
自動化的管理內存資源,垃圾回收機制必需要有一套算法來進行計算,哪些是有效的對象,哪些是無效的對象,對於無效的對象就要進行回收處理。
常見的垃圾回收算法有:引用計數法、標記清除法、標記壓縮法、複製算法、分代算法等。編程
引用計數是歷史最悠久的一種算法,最先George E. Collins在1960的時候首次提出,50年後的今天,該算法依然被不少編程語言使用jvm
1.原理
假設有一個對象A,任何一個對象對A的引用,那麼對象A的引用計數器+1,當引用失敗時,對象A的引用計數器就-1,若是對象A的計數器的值爲0,就說明對象A沒有引用了,能夠被回收。編程語言
2.優缺點優化
優勢:spa
缺點:線程
什麼是循環引用?code
class TestA{ public TestB b; } class TestB{ public TestA a; } public class Test { public static void main(String[] args) { TestA a=new TestA(); TestB b=new TestB(); a.b=b; b.a=a; a=null; b=null; } }
雖然a和b都爲null,可是因爲a和b存在循環引用,這樣a和b永遠都不會被回收。對象
標記清除算法,是將垃圾回收分爲2個階段,分別是標記和清除。
1.原理
這張圖表明的是程序運行期間全部對象的狀態,它們的標誌位所有是0(也就是未標記,如下默認0就是未標記,1爲已標記),假設這會兒有效內存空間耗盡了,JVM將會中止應用程序的運行並開啓GC線程,而後開始進行標記工做,按照根搜索算法,標記完之後,對象的狀態以下圖。
能夠看到,按照根搜索算法,全部從root對象可達的對象就被標記爲了存活的對象,此時已經完成了第一階段標記。接下來,就要執行第二階段清除了,那麼清除完之後,剩下的對象以及對象的狀態以下圖所示。
能夠看到,沒有被標記的對象將會回收清除掉,而被標記的對象將會留下,而且會將標記位從新歸0。接下來就不用說了,喚醒中止的程序線程,讓程序繼續運行便可。
2.優缺點
能夠看到,標記清除算法解決了引用計數算法中的循環引用的問題,沒有從root節點引用的對象都會被回收。一樣,標記清除算法也是有缺點的:
標記壓縮算法是在標記清除算法的基礎之上,作了優化改進的算法。和標記清除算法同樣,也是從根節點開始,對對象的引用進行標記,在清理階段,並非簡單的清理未標記的對象,而是將存活的對象壓縮到內存的一端,而後清理邊界之外的垃圾,從而解決了碎片化的問題。
1.原理
2.優缺點
優缺點同標記清除算法,解決了標記清除算法的碎片化的問題,同時,標記壓縮算法多了一步,對象移動內存位置的步驟,其效率也有有必定的影響。
複製算法的核心就是,將原有的內存空間一分爲二,每次只用其中的一塊,在垃圾回收時,將正在使用的對象複製到另外一個內存空間中,而後將該內存空間清空,交換兩個內存的角色,完成垃圾的回收。
若是內存中的垃圾對象較多,須要複製的對象就較少,這種狀況下適合使用該方式而且效率比較高,反之,則不適合。
1.JVM中年輕代內存空間
2.優缺點
優勢:
缺點:
前面介紹了多種回收算法,每一種算法都有本身的優勢也有缺點,誰都不能替代誰,因此根據垃圾回收對象的特色進行選擇,纔是明智的選擇。
分代算法其實就是這樣的,根據回收對象的特色進行選擇,在jvm中,年輕代適合使用複製算法,老年代適合使用標記清除或標記壓縮算法。