JVM那些事兒,GC(二)

我是方圓,簡單入入JVM的門兒

1. GC的作用範圍

在這裏插入圖片描述

2. 四種GC算法

  1. 引用計數算法
    對象創建的時候,就給對象綁定一個計數器。每當有一個引用指向該對象時,計數器加一;每當有引用消除時,計數器減一。在沒有引用,即計數器爲0時,這個對象被垃圾回收。(JVM的實現不採用這種算法
  • 優點:比較簡單;
  • 缺點:無法解決對象循環引用的問題;需要佔用額外空間
  1. 複製算法
    該算法應用於兩個倖存區中。每次只佔用其中一個倖存區,每進行一次MinorGC,將存活下來的對象複製到另一個空的倖存區(to)中,然後之前的倖存區被清空,稱爲to,而另一個由空變爲非空,稱爲From
  • 優點:不產生內存碎片
  • 缺點:有一部分內存浪費(to區)
  1. 標記清除算法
    在這裏插入圖片描述
    這個算法分爲如下兩個階段,標記階段:遍歷所有的GC Roots,並將所有的存活對象進行標記(這裏簡單說一下可達性分析算法,只有對象可達的纔會被標記);清除階段:將遍歷堆中所有的對象,將沒有被標記的對象清除。
  • 優點:相比於引用計數算法,開銷更小
  • 缺點:算法複雜度較高,效率比較低;沒有移動對象,這種方式清理出的內存不是連續的(碎片化)
  1. 標記整理算法
    標記整理算法是標記清除算法的改進版,適用於老年代的垃圾回收。它們在標記階段做的工作是相同的,只不過在第二個階段,該算法並沒有直接對死亡的對象進行清理,而是對所有存活的對象進行整理,放到一處存儲空間,然後再把剩下的死亡對象全部清除。

標記:從根集合進行掃描,對存活的對象進行標記
清除:移動所有存活的對象,並且按照內存地址次序依次排列,然後將末端內存地址以後的內存全部回收

  • 優點:不產生碎片空間,解決了標記清除算法碎片化的問題
  • 缺點:若存活的對象很多,則效率很低

3. 什麼對象會晉升到老年代?

  • 默認情況經歷15次Minor GC依然存活的對象
  • Surivor區中存放不下的對象
  • 新生成的對象(-XX:PretenuerSizeThreshold 這個參數可以調節對象大小的閾值,超過這個閾值則會被放在老年代)

4. 常用的調優參數

  • -XX: SurvivorRatio Eden和Survivor的比值,默認8:1
  • -XX:NewRatio 老年代和年輕代內存大小的比值,默認2:1
  • -XX:MaxTenuringThreshold 對象從年輕代晉升到老年代,經過的GC次數的閾值
  • -XX:+PretenuerSizeThreshold 大對象直接放入老年代文件大小的閾值

5. 觸發Full GC的條件

  1. 老年代空間不足
  2. 調用System.gc();
  3. 永久代空間不足(JDK1.7及之前)
  4. CMS GC時出現 promotion failed,concurrent mode failure
  5. Minor GC 晉升到老年代的平均大小大於老年代剩餘空間
  6. 使用RMI來進行RPC或管理的JDK應用,每小時執行1次Full GC

6. Stop-the-world 和 Safepoint

  1. Stop-the-world

JVM進行任何GC都會停止應用程序的執行,多數GC的優化就是減少了Stop-the-world來提高性能

  1. Safepoint

安全點是對象引用關係不會發生變化的點,產生安全點的地方,方法調用;循環跳轉;異常跳轉等,線程停頓就需要停在安全點處

7. JVM的運行模式

  1. Server:啓動慢,運行快(重量級虛擬機)
  2. Client:啓動快,運行慢(輕量級虛擬機,可用java -version命令查看)

8. 常見的垃圾收集器

在這裏插入圖片描述

8.1 年輕代常見的垃圾收集器

  1. Serial收集器(-XX:+UseSerialGC,複製算法)
    單線程垃圾收集,必須暫停所有的工作線程
    簡單高效,Client模式下默認使用的年輕代收集器
  2. ParNew收集器(-XX:+UseParNewGC,複製算法)
    多線程收集,其餘的行爲和Serial收集器一樣
    單核執行效率不如Serial收集器,在多核下優勢明顯
  3. Parallel Scavenge收集器(-XX:+UseParallelGC,複製算法)
    更關注吞吐量,適合用於後臺服務,更好的利用CPU,而不適合用於交互(吞吐量=執行代碼的時間/(執行代碼的時間 + 垃圾回收的時間)
    在多核情況下優勢明顯,是Server默認使用的年輕代收集器

8.2 老年代常見的垃圾收集器

  1. Serial Old收集器(-XX:+UseSerialOldGC,標記-整理算法)
    單線程垃圾收集,必須暫停所有的工作線程
    簡單高效,Client模式下默認老年代收集器
  2. Parallel Old收集器(-XX:+UseParallelOldGC,標記-整理算法)
    多線程下,吞吐量優先
  3. CMS收集器(-XX:+UseConcMarkSweepGC,標記-清除算法)
    很屌的收集器,幾乎能與工作線程同時進行,減少了Stop-the-world的時間

8.3 年輕代和老年代都能用的收集器

  • GarbageFirst收集器(-XX:+UseG1GC,複製算法+標記整理算法)
  • 特點:並行和併發;分代收集;可預測的停頓;空間整合
  • 工作方式:將整個Java堆內存劃分成多個大小相同的Region,年輕代和老年代不再物理隔離

在這裏插入圖片描述

同系列

JVM那些事兒,這些必會的知識點(一)

參考文獻

JVM的四種GC算法

JVM:GC(垃圾回收算法)

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