JVM之垃圾收集(Garbage Collection [Ⅱ])

7 個垃圾收集器

垃圾收集器就是內存回收操做的具體實現,HotSpot 有 7 種。由於它們各有各的適用場景。有的屬於新生代收集器,有的屬於老年代收集器,因此通常都是搭配使用的。關於它們的簡單介紹以及分類請見下圖。算法

Serial 收集器

特色:數組

1.「單線程」操做。會產生「Stop The World」。
2.採用"Stopr the world"。
3.Serial 收集器是虛擬機在 Client模式下的默認新生代收集器,它的優點是簡單高效,適合單 CPU 模式。
複製代碼

ParNew 收集器

特色:

1.其自己就是 Serial 收集器的多線程版本。雖然除此以外沒什麼創新之處,但它倒是許多運行在 Server 模式下的虛擬機中的首選新生代收集器。

2.除了 Serial 收集器外,只有它能和 CMS 收集器搭配使用。
複製代碼

Parallel Scavenge 收集器

特色:

1.新生代收集器,並行的多線程收集器。
2.使用複製算法,
3.可控制吞吐量(Throughput)。
複製代碼

吞吐量 = 運行用戶代碼時間 / ( 運行用戶代碼時間 + 垃圾收集時間 )安全

可調節的虛擬機參數:多線程

  • -XX:MaxGCPauseMillis:最大 GC 停頓的秒數;
  • -XX:GCTimeRatio:吞吐量大小,一個 0 ~ 100 的數,最大 GC 時間佔總時間的比率 = 1 / (GCTimeRatio + 1)
  • -XX:+UseAdaptiveSizePolicy:一個開關參數,打開後就無需手工指定 -Xmn-XX:SurvivorRatio 等參數了,虛擬機會根據當前系統的運行狀況收集性能監控信息,自行調整。

Serial Old 收集器

特色:

1.Serial收集器的老年代版,同爲單線程。
2.使用標記整理算法。
3.做爲CMS收集容器的後備預案。
複製代碼

Prallel Old 收集器

特色:

1.Parallel Old收集器的老年代版,多線程。
2.使用標記-整理算法。
複製代碼

CMS 收集器(Concurrent Mark Sweep)

特色:併發

1.CMS注重於服務的響應速度,但願系統停頓時間最短。
2.基於「標記-清除」算法實現的。【注1】
3.存在如下幾點缺點:
    (1)CMS收集器對CPU資源很是敏感。
    (2)CMS收集器沒法處理浮動垃圾。
    (3)因爲基於標記-清除算法,因此會產生大量碎片
複製代碼

【注1】 標記-清除算法步驟: 1.初始標記 2.併發標記 3.從新標記 4.併發清除性能

參數設置:spa

  • -XX:+UseCMSCompactAtFullCollection:在 CMS 要進行 Full GC 時進行內存碎片整理(默認開啓)
  • -XX:CMSFullGCsBeforeCompaction:在多少次 Full GC 後進行一次空間整理(默認是 0,即每一次 Full GC 後都進行一次空間整理)

關於 CMS 使用 標記 - 清除 算法的一點思考:線程

以前對於 CMS 爲何要採用 標記 - 清除 算法十分的不理解,既然已經有了看起來更高級的 標記 - 整理 算法,那 CMS 爲何不用呢?最近想了想,感受多是這個緣由,不過也不是很肯定,只是我的的一種猜想。指針

標記 - 整理 會將全部存活對象向一端移動,而後直接清理掉邊界之外的內存。這就意味着須要一個指針來維護這個分隔存活對象和無用空間的點,而咱們知道 CMS 是併發清理的,雖然咱們啓動了多個線程進行垃圾回收,不過若是使用 標記 - 整理 算法,爲了保證線程安全,在整理時要對那個分隔指針加鎖,保證同一時刻只有一個線程能修改它,加鎖的這一過程至關於將並行的清理過程變成了串行的,也就失去了並行清理的意義了。日誌

因此,CMS 採用了 標記 - 清除 算法。

G1 收集器

特色: 1.並行併發。 2.分代收集。 3.空間整合。 4.可預測的停頓。

G1運算步驟

1.初始標記
2.併發標記
3.最終標記
4.篩選回收
複製代碼

GC 日誌解讀

Java 內存分配策略

新生代和老年代的 GC 操做:

  • 新生代 GC 操做:Minor GC
    • 發生的很是頻繁,速度較塊。
  • 老年代 GC 操做:Full GC / Major GC
    • 常常伴隨着至少一次的 Minor GC;
    • 速度通常比 Minor GC 慢上 10 倍以上。

優先在 Eden 區分配

  • Eden 空間不夠將會觸發一次 Minor GC;
  • 虛擬機參數:
    • -Xmx:Java 堆的最大值;
    • -Xms:Java 堆的最小值;
    • -Xmn:新生代大小;
    • -XX:SurvivorRatio=8:Eden 區 / Survivor 區 = 8 : 1

大對象直接進入老年代

  • 大對象定義: 須要大量連續內存空間的 Java 對象。例如那種很長的字符串或者數組。
  • 設置對象直接進入老年代大小限制:
    • -XX:PretenureSizeThreshold:單位是字節;
      • 只對 Serial 和 ParNew 兩款收集器有效。
    • 目的: 由於新生代採用的是複製算法收集垃圾,大對象直接進入老年代能夠避免在 Eden 區和 Survivor 區發生大量的內存複製。

長期存活的對象將進入老年代

  • 固定對象年齡斷定: 虛擬機給每一個對象定義一個年齡計數器,對象每在 Survivor 中熬過一次 Minor GC,年齡 +1,達到 -XX:MaxTenuringThreshold 設定值後,會被晉升到老年代,-XX:MaxTenuringThreshold 默認爲 15;
  • 動態對象年齡斷定: Survivor 中有相同年齡的對象的空間總和大於 Survivor 空間的一半,那麼,年齡大於或等於該年齡的對象直接晉升到老年代。
相關文章
相關標籤/搜索