垃圾回收算法的好壞直接影響到程序運行效率,接下來對幾種常見的回收算法進行介紹么夫。
標記-清除算法(Mark-Sweep)
該算法是最基礎的收集算法者冤,算法分“標記”和“清除”兩部分。 回收過程是標記出需要所有需要回收的對象档痪,在標記完成后統(tǒng)一回收被標記的對象
- 不足
- 標記和清除兩個過程效率并不高涉枫。
-
標記清理過后會產生大量的不連續(xù)的碎片內存,空間內存碎片太多會導致在需要分配大對象時找不到合適的連續(xù)內存進行分配腐螟。這樣就會提前觸發(fā)一次垃圾回收動作愿汰。執(zhí)行過程如下圖:
標記-清除算法示意圖
復制算法(Copying)
為了解決效率問題而出現(xiàn)了復制算法。它將內存劃分為大小兩塊相等的內存乐纸,每次只使用其中一塊衬廷,當這塊內存用完了就將還存活的對象復制到另一塊上,然后把剛剛那塊用完了的內存全部清理汽绢,每次都是對半個內存區(qū)域進行回收吗跋,所以在內存分配時不用考慮內存碎片的問題。
- 優(yōu)點
算法實現(xiàn)簡單高效 - 缺點
將原來將原來可用內存縮小了一半,代價昂貴跌宛。
標記-整理算法(Mark-Compact)
復制算法在存活對象較多的情況下效率比較低酗宋,更關鍵的是不想浪費50%的內存空間,那么就需要有額外的空間進行分配擔保秩冈,已應對100%存活對象的這種極端情況本缠。因此在老年代使用標記-整理算法。
-
算法過程
標記過程和標記-清理算法一致入问,而后續(xù)步驟則先將所有存活的對象移至一端丹锹,然后直接清理掉端邊界以外的對象。
標記-整理算法
分代收集算法(Generation Collection)
-
堆內存劃分
在 Java 中芬失,堆被劃分成兩個不同的區(qū)域:新生代 ( Young )楣黍、老年代 ( Old )。新生代 ( Young ) 又被劃分為三個區(qū)域:Eden棱烂、From Survivor租漂、To Survivor。
20160818221750646.jpg
在默認情況下
新生代 ( Young ) 與老年代 ( Old ) 的比例的值為 1:2
Eden : from : to = 8 : 1 : 1
JVM 每次只會使用 Eden 和其中的一塊 Survivor 區(qū)域來為對象服務颊糜,所以無論什么時候哩治,總是有一塊 Survivor 區(qū)域是空閑著的。
因此衬鱼,新生代實際可用的內存空間為 9/10 ( 即90% )的新生代空間业筏。
注 堆內存劃分 摘自: java堆內存劃分,詳情點鏈接查看
分代收集算法根據(jù)堆中對象生存周期的不同鸟赫,對各個區(qū)域采用不同的搜集算法蒜胖。在新生代中每次搜集都有大量的對象死去,少量的對象存活抛蚤,所以在這個區(qū)域采用“復制算法”台谢,而在老年代,對象存活率高岁经,沒有額外的內存分配擔保朋沮,那么它必須使用“標記-整理“或”標記-清除“算法。