jvm垃圾收集器你學廢了嗎(一)

前言

前面一篇文章講了垃圾回收的算法(傳送門),今天來說一下從古到今一些經典的垃圾收集器,直接進入正題!

Serial 收集器

Serial 收集器也算上是一個老古董了,看到這個名字,我們就可以猜到這是一個單線程工作的收集器,採用的是標記-複製算法,這裏的單線程不僅說它使用一個處理器或者一條線程,而是它必須暫停其他所有工作的線程,Stop The World 這個世界都暫停了,可想而知,你的電腦說不定在某個時刻就要暫停下來等待垃圾回收,這是多麼糟糕的一件事情!
在這裏插入圖片描述
但是它依然是HotSpot虛擬機運行在客戶端模式下的默認新生代收集器,這時候問題來了 什麼是客戶端模式呢,是不是還有服務器模式呢
如果是64位的jdk,只能運行在Server模式下。而32位的jdk,默認是運行在client模式下,可以通過修改設置來指定默認的啓動模式。
還可以通過在cmd命令行窗口用 java -version 查看
在這裏插入圖片描述

優點

  • 簡單而高效
  • 沒有其他的內存消耗,所以說內存消耗小

缺點就不用我多說了吧

ParNew 收集器

ParNew 收集器實質上是Serial收集器的多線程版本,這裏講的多線程是多個垃圾收集的線程,採用的是標記-複製算法,並不是垃圾收集線程和用戶線程並行,它也是用於新生代的收集器,相比Serial 並沒有太多的創新,之後或說到一個CMS收集器,它的出現讓ParNew 又活了一段時間,CMS作爲老年代的收集器,ParNew 作爲新生代的收集器。
但是好景不長,隨着技術的日益發展,G1收集器的出現讓ParNew徹底的退出了歷史舞臺(後面都會介紹)
在這裏插入圖片描述

優點

  • 在多核處理器上,ParNew收集器對系統資源的高效利用還是很有好處的

缺點

  • 在單核處理器上ParNew的效果遠不及Serial收集器,因爲存在線程交互的開銷

Parallel Scavenge 收集器

Parallel Scavenge 收集器也是一款新生代的垃圾收集器,同樣採用標記-複製算法,很多地方都和ParNew 收集器神似。但是它有它的獨特之處!
在這裏插入圖片描述
Parallel Scavenge 收集器目標是一個可控制的吞吐量,這時候問題來了 什麼是吞吐量呢
吞吐量就是處理器運行代碼的時間和處理器使用的總時間的比值,Parallel Scavenge 收集器提供了兩個參數:

  • -XX:MaxGCPauseMillis 控制最大垃圾收集的停頓時間
    參數值 是一個大於0的毫秒數,收集器在每次垃圾回收的時間不是超過這個值,不過大家不用以爲把這個值調到很小,這樣垃圾回收的效率就高了,這個想法是錯誤的,它犧牲了吞吐量和新生代的空間,比如說收集50M的空間肯定比收集100M的空間速度要快,之前10秒收集一次,每次需要100毫秒,現在3秒收集一次,每次耗時40毫秒,這會使垃圾回收的次數頻繁,所以這個值一定要設置的合理
  • -XX:GCTimeRatio 直接設置吞吐量的大小
    參數值是大於0小於100的整數,比如我們設置19,允許垃圾回收的時間佔總時間的5% (1/(1+19)),默認值是99 也就是垃圾回收的時間在總時間的1%

優點

  • Parallel Scavenge 收集器的優點就是它提供了一個-XX:+UseAdaptiveSizePolicy的一個參數,這是一個開關參數,如果它被激活了,就不需要人工的指定新生代、Eden、Survivor區域的大小、晉升老年代對象的大小等細節參數,虛擬機會個根據當前系統的運行情況提供最合適的策略

缺點

  • Stop The World

Serial Old 收集器

Serial Old 收集器是Serial 老年代版本,同樣也是單線程收集器, 使用標記-整理算法, 這個收集器和Serial 基本一樣,這裏就不做闡述,它與Parallel Scavenge收集器配合使用

Parallel Old 收集器

Parallel Old 收集器,這個收集器說來也是尷尬,他是Parallel Scavenge 收集器的老年代版本,支持多線程併發收集,也是基於標記-整理算法,在早期Parallel Scavenge 收集作爲新生代的垃圾收集器,它只能選擇Serial Old作爲老年代的垃圾收集器,沒有別的選擇,但是由於單線程的老年代收集無法充分利用服務器多處理的並行處理能力,在服務器應用性能上的拖累,無法滿足Parallel Scavenge 收集器吞吐量最大化!
在這裏插入圖片描述
所以Parallel Old 收集器的出現就是爲了配合Parallel Scavenge 收集器,使得吞吐量最大化,也是名副其實的吞吐量優先組合

CMS 收集器

CMS 收集器是一款以獲取最短回收停頓時間爲目標的收集器,它是基於標記-清除算法實現的,它的運作過程很複雜,分爲4步,下面具體的說一下每一步

  • 初始標記
    初始標記仍然需要Stop The World ,它僅僅是標記一下GC Roots能直接關聯的對象,速度很快
  • 併發標記
    從GC Roots對象 開始遍歷整個對象圖,這個過程用時很長,但是和用戶線程一起併發執行,就是不需要用戶等待
  • 重新標記
    重新標記也需要Stop The World,修正在上一步併發標記的過程中,因爲用戶程序的運行導致一部分對象的引用發生了變化,這個階段的時間也很短,
  • 併發清理
    清理掉已經標記死亡的對象,這個過程也不需要用戶等待,與用戶線程併發執行

優點

  • 併發收集,低停頓

缺點

  • CMS收集器是併發的,所以它會佔用一部分線程,導致應用程序變慢
  • 無法處理浮動垃圾
    至於 “浮動垃圾”,因爲 CMS 在 併發標記 時是併發的,GC 線程和用戶線程併發執行,這個過程當然可能會因爲線程的交替執行而導致新產生的垃圾(即浮動垃圾)沒有被標記到;而 重新標記 的作用只是修改之前 併發標記 所獲得的不可達對象,所以是沒有辦法處理 “浮動垃圾” 的。
  • 它是基於標記–清除算法的,肯定會產生內存碎片

總結

篇幅有點長了後面的文章還會更新G1收集器、Shenandoah收集器、ZGC收集器等優秀的垃圾收集器
上面的幾種垃圾收集器,你學廢了嗎?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章