java中的垃圾回收算法與垃圾回收器

常用的垃圾回收算法標記-清除標記清除算法是一種非移動式的回收算法,分為標記 清除 2個階段,簡而言之就是先標記出需要回收的對象,標記完成后再回收掉所有標記的內存對象,如下圖
【java中的垃圾回收算法與垃圾回收器】

java中的垃圾回收算法與垃圾回收器

文章插圖
可見回收后圖中被標記的對象被刪除回收了,但是碎片化比較嚴重不連續 對于下次分配大對象的時候由于內存不連續性影響比較大,而且每一次Gc的時候需要執行2個操作 1次標記 1次回收
標記-整理壓縮標記整理壓縮算法是一種移動式的算法,由于上面標記清除算法導致內存不連續的問題 標記-整理算法就解決了這個問題 。
java中的垃圾回收算法與垃圾回收器

文章插圖
工作原理也是2階段操作而且更復雜了,首先找出(root)根地址的對象一直尋找標記是否被引用,引用了就標記一下 , 標記完成后把標記的對象按順序移動排列在一起并清除掉邊界的未標記的對象 , 這樣就沒有內存碎片 。
缺點
  • 由于標記完成后需要移動對象 移動的過程可能會產生STW
  • 2次+調整指針
復制算法復制算法更粗暴了 , 邏輯也很簡單 通常直接申明了2塊一樣大小存儲空間,每次只使用其中1塊空間,當使用的這塊空間不夠用的時候就觸發回收操作,將存活的對象copy到另一塊空間中按順序存放,可回收的就回收刪除掉,這樣一來就不會出現內存碎片,但是要多浪費50%的內存空間,主要用于年輕代 比如s0 s1亦是如此 。
java中的垃圾回收算法與垃圾回收器

文章插圖
分代回收算法根據對象的存活周期劃分為新生代、老年代 。因此可以根據不同年代的特點使用不同的回收算法 。分代收集目前是大部分JVM
  • 新生代特點
    在新生代中大量的對象產生 又有大量的對象需要銷毀,他們存活時間都比較短 。基本上都是回收的時候大部分會被回收掉,只有少量的對象是存活不回收的 。
    存活對象少,垃圾對象多這就比較適合使用復制算法,復制算法需要用到2塊內存空間 每次只使用其中一塊 , 在jdk8中不只是單純的劃分為s0 s1 二塊存儲空間 , 還新增了一塊Eden ,s0 s1的默認大小是eden的8/1 這樣設計的目的在于每次觸發回收的時候把90(eden+其中1個s區)的區域中存活的對象copy到10%的存儲中 , 理論上清除了90%的空間 , 這樣做的好處就是不需要花50%的存儲空間,只浪費了10%的空間就實現了這個算法邏輯 。
  • 老年代特點
    老年代的特點就是對象存活時間都比較長 , 大量的存活對象就不適合像新生代一樣用復制算法了 因為copy的成本太高 , 這種就比較適合標記清除算法,或者標記清除整理算法 。
    優缺點概述
    算法名稱優點缺點標記-清除簡單位置不聯系 碎片化嚴重 效率低 2次掃描標記-壓縮整理沒有碎片效率低 2次掃描 可能會多次重置指針復制算法沒有碎片 簡單高效浪費空間
垃圾回收器上面的垃圾算法僅僅只是一個理論上的算法 ,正在實現這些算法的叫垃圾回收器,在工作中具體是怎么回收工作的可以不關心 , 但是需要了解不同的垃圾回收器是基于哪種算法實現的,有助于出現性能問題的時候有思路去參數調優,而不是盲目的問度娘 。各個年輕代 老年代垃圾回收器可組合配對方式如下圖所示
java中的垃圾回收算法與垃圾回收器

文章插圖
java中的垃圾回收算法與垃圾回收器

文章插圖
serial串行收集器serial回收器是一個串行單線程回收器 , 在進行垃圾回收的時候必須暫停用戶工作線程,直到回收線程處理完成,每次回收必然會STW 。比較適合跑在client端應用
java中的垃圾回收算法與垃圾回收器

文章插圖
ParNew收集器ParNew回收器是新生代垃圾回收器, 就是serial的多線程版本 其它基本上serial差不多的,在ps回收器沒有出來之前parNew+cms是服務器端首選
java中的垃圾回收算法與垃圾回收器

文章插圖
Parallel Scavenge收集器常說的ps 收集器就算它,ps是一個新生代收集器采用復制算法,多線程并行收集 。是jdk8的默認新生代回收器 。
看起來和parNew有點一樣 反正性能就是比它要強,在應用吞吐量方面更優秀 。ps一般是和Parallel Old配合使用

推薦閱讀