這裏簡要介紹幾種垃圾收集算法的思想算法
該算法如同它的名字同樣,分爲「標記」和「清除」兩個階段:安全
這個算法其實已通過時了,可是後續的算法都是基於這種思路來的。它主要的不足點有兩個:數據結構
複製算法的流程以下:線程
能夠看到每次只對一半區域進行收集,這樣就不用考慮內存碎片等複雜狀況了,只要移動堆頂指針,按順序分配內存便可,實現簡單,運行高效。可是這種算法的代價是將內存縮小爲原來的一半,內存成本高指針
複製算法通常用於收集新生代,由於新生代大部分的對象的存活時間很短,所以新生代中存活的對象遠遠少於垃圾對象。cdn
新生代:存放年輕對象的堆空間。年輕對象是指剛剛建立,或者經歷垃圾回收次數很少的對象。
老年代:存放老年對象的堆空間。老年對象指經歷過屢次垃圾回收依然存活的對象。對象
在商業虛擬機中,例如咱們常見的HotSpot虛擬機,將新生代分爲一個Eden區和兩個Survivor區,Eden區與Survivor區的大小比例是8:1,也便是說Eden區佔新生代的80%,兩個Survivor分別佔10%。新生代的複製算法執行規則以下:blog
能夠發現,這種複製機制保證只有一塊Survivor區的內存(僅佔新生代內存的10%)是被浪費的。新生代的複製算法示意圖以下:事件
在對象存活率較低的新生代使用複製算法效率高。那麼在對象存活率高的老年代,使用複製算法效率將會變得很低。根據老年代的特色,有人提出了「標記 - 整理」算法。算法流程以下:內存
當前商業虛擬機的垃圾收集算法都採用「分代收集算法」。主要思想是根據對象存活週期的不一樣將內存劃分爲幾塊,並採用最適合的收集算法。
上面介紹了幾種垃圾收集算法,可是虛擬機(這裏以HotSpot爲例子)在發起內存回收的時候會遇到不少問題。所以誕生了OopMap、Safe Point和Safe Region來解決
問題:
解決: 在HotSpot的實現中,使用一組成爲OopMap的數據結構。
這樣,GC在掃描時就能夠直接得知這些信息了。
在OopMap的協助下,HotSpot能夠快速且準確地完成GC Roots枚舉,但一個很現實的問題隨之而來:
解決:
對於Safe Point,另外一個須要考慮的問題是如何在GC發生時讓全部線程(這裏不包括執行JNI調用的線程)都運行到最近的安全點上再停頓下來。這裏有兩種方案可供選擇:搶先式中斷(Preemptive Suspension)和主動式中斷(Voluntary Suspension):
Safe Point機制保證了程序執行時,在不太長的時間內就會遇到可進入GC的Safe Point。 問題:
安全區域是指在一段代碼片斷之中,引用關係不會發生變化。在這個區域中的任意地方開始GC都是安全的。咱們也能夠把Safe Region看作是被擴展了的Safepoint。
在線程執行到Safe Region中的代碼時,首先標識本身已經進入了Safe Region,當在這段時間裏JVM要發起GC時,就不用管標識本身爲Safe Region狀態的線程了。在線程要離開Safe Region時,它要檢查系統是否已經完成了根節點枚舉(或者是整個GC過程),若是完成了,那線程就繼續執行,不然它就必須等待直到收到能夠安全離開Safe Region的信號爲止。