文章目錄
Pre
JVM-04垃圾收集Garbage Collection(上)【垃圾對象的判定】
JVM-05垃圾收集Garbage Collection(中)【垃圾收集算法】
JVM-06垃圾收集Garbage Collection(下)【垃圾收集器】
分代收集理論
當前虛擬機的垃圾收集都採用分代收集算法 , 意思就是根據對象存活週期的不同將 java堆分爲新生代和老年代,這樣就可以根據各個年代的特點選擇合適的垃圾收集算法。
舉個例子,新生代中,大部分對象都是朝生夕死的,所以可以選擇複製算法, 只複製那些少量存活的對象。
而老年代,絕大部分都是一些頑固的對象,存貨週期較長,如果選擇複製算法,就要複製很多對象,效率自然不高 ,所以得換個算法,通常會選擇標記-清除”或“標記-整理”算法進行垃圾收集。
常見的垃圾收集算法
標記-清除算法
兩個階段 “標記” + “清除”
- 標記存活的對象, 也可以反過來,標記出所有需要回收的對象
- 標記完成後,統一回收所有未被標記的對象(一般選擇這種)
存在兩個問題
- 如果需要標記的對象太多,效率不高 【效率問題】
- 標記清除後會產生大量不連續的碎片 【內存碎片】
基於這個缺點,進化除了 標記-整理 ,多了一步整理內存碎片。
標記-複製算法
它將內存分爲大小相同的兩塊,每次使用其中的一塊。
當這一塊的內存使用完後,就將還存活的對象複製到另一塊去,然後再把使用的空間一次清理掉。
這樣就使每次的內存回收都是對內存區間的一半進行回收。
-
優點:常用於新生代,存活的對象少,複製這些存活的對象,效率高。
-
缺點 顯而易見: 浪費空間
標記-整理算法
根據老年代的特點演化出一種標記算法, 標記過程同“標記-清除” 。
移動所有存活的對象,且按照內存地址次序依次排列,然後將末端內存地址以後的內存全部回收。因此,第二階段才稱爲整理階段。
垃圾收集器
爲什麼會有這麼多GC 回收器?
因爲目前沒有任何一款是十分完美的,我們需要做的就是充分了解這些GC Collector 根據業務特點選擇合適的GC Collector 。
Serial收集器
兩個收集器 。一個 新生代Serial , 一個 老年代 Serial Old .
新生代採用複製算法,老年代採用標記-整理算法。
JVM參數
-XX:+UseSerialGC (新生代) -XX:+UseSerialOldGC (老年代)
Serial(串行)收集器是最基本、歷史最悠久的垃圾收集器 。
字面意思:
- 單線程GC
- GC的時候STW
- 新生代 Serial , 複製算法
- 老年代Serial Old , 標記整理算法
Serial Old收集器是Serial收集器的老年代版本,也是一個單線程收集器。
它主要有兩大用途:
- 一種用途是在JDK1.5以及以前的版本中與Parallel Scavenge收集器搭配使用,
- 另一種用途是作爲CMS收集器的後備方案。
Parallel Scavenge收集器 【JDK8默認】
Serial收集器的多線程版本
JVM參數
-XX:+UseParallelGC(年輕代),-XX:+UseParallelOldGC(老年代)
默認的收集線程數跟cpu核數相同,當然也可以用參數(-XX:ParallelGCThreads
)指定收集線程數,但是一般不推薦修改。
Parallel Scavenge收集器關注點是吞吐量(高效率的利用CPU)
CMS等垃圾收集器的關注點更多的是用戶線程的停頓時間(提高用戶體驗)
新生代採用複製算法,老年代採用標記-整理算法。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本。使用多線程和“標記-整理”算法。
在注重吞吐量以及CPU資源的場合,都可以優先考慮 Parallel Scavenge收集器和Parallel Old收集器(JDK8默認的新生代和老年代收集器)。
ParNew收集器
What ? ParNew ? 不是有個Parallel 嗎? 又出來這個主要是因爲Parallel 不能和CMS搭配使用,所以官方又弄出個這麼個玩意兒。
JVM參數
-XX:+UseParNewGC
ParNew收集器其實跟Parallel收集器很類似,區別主要在於它可以和CMS收集器配合使用。
新生代採用複製算法,老年代採用標記-整理算法。
互聯網公司 小內存的機器 主流的GC組合 就是 ParNew + CMS .
CMS 【重點掌握】
JVM參數
-XX:+UseConcMarkSweepGC(老年代)
詳細的四個步驟、CMS存在的問題以及三色標記我們下篇博文繼續展開