話不多說,直接上內容,書中介紹了四種算法。
1. 標記-清除算法:這是最基礎的算法,後續的算法都是在此算法基礎上做出的改進。
該算法包括兩個過程:
標記——將對象回收狀態進行標記,這個在以前的筆記中已經做了介紹,這裏不再贅述。
清除——回收的時候直接將標記爲可回收的對象清除。
缺點:1.1效率問題:標記和清除兩個過程的效率都不高;
1.2. 空間問題:從圖中可以看出,回收之後的內存上產生了大量不連續的內存碎片,過小的內存空間不能被分配給大的對象使用,只能佔用更大的空閒內存空間,這樣又會產生新的內存碎片,直至無法滿足更大的內存需求,就要開始又一次垃圾收集。
2. 複製算法:解決標記-清除算法的效率問題(適用於新生代)。
算法思想:將內存分爲相等的兩塊,比如a和b,程序運行時的內存分配都在a中操作,當垃圾回收的時候(在回收之前標記過程還是有的),將a中需要存活的對象信息依次直接複製到b上(這樣,在b中的內存使用一直都是連續的),然後把a的空間直接清空(這簡直是truncate table a和delete from a where id in(1,2,3,4……)的差距)。
缺點:內存的最大可用空間變爲只有原來的一半。
原書中的配圖是這樣的,筆者感覺下面圖的看起來更加直觀一些。
另外,現代的商業虛擬機(包括JAVA的HotSpot)都是採用這種方法回收新生代。
不過這裏不是按照1:1分配的了,而是將Eden,Survivor(From),Survivor(To)三個區域(對新生代、老年代不太明確的,有疑問的話可以看一下上一篇,已經特別介紹過了)按照8:1:1分配的。
其中Eden和Survivor(From)可以當作上圖中的a,佔90%;Survivor(To)相當於b,佔10%。
之所以這樣分配是因爲新生代中的對象生命週期較短,回收率非常高(IBM研究表明達到98%)。
這裏還有一種情況,當a回收時,存活對象大於10%,即超過b的空間大小的時候,這些對象將通過分配擔保機制進入到老年代。
3. 標記-整理算法:解決複製算法在對象存活率較高,要進行多次複製,效率變低的問題(老年代上的對象存活率很高,此算法適用於老年代)。
步驟:首先也是標誌對象回收狀態。然後進行整理,將存活的對象向一端挪動,將存活的對象集中到一端,剩下的全部作爲可用空間。示意圖如下:
4. 分代收集算法:實際上就是根據不同的對象存活週期的特點採用不同算法進行回收,上面對於適用的情況已經做出了描述。
怎麼樣,其實對照的看一下,是不是很簡單。
喜歡文章或想一起學習的朋友可以關注我,我將會持續更新,有什麼疑問或文中有不當之處請給我留言,真誠地希望能與大家一起交流探討,學習進步。