JVM基礎知識-GC垃圾回收機制

垃圾收集(Garbage Collection):通常被稱為"GC",由虛擬機"自動化"完后垃圾回收工作

1.前言

上一章講解的JVM內存結構,知道程序計數器是唯一沒有OutOfMemoryError的區域,堆是垃圾回收的主要區域,本章繼續學習JVM相關知識,了解Java GC的底層原理

2.目錄

目錄

3.GC垃圾回收機制

JVM中程序計數器,虛擬機棧,本地方法棧3個區域隨線程而生隨線程而滅,棧幀隨著方法的進入和退出做入棧和出棧操作,實現了自動的內存清理.它們的內存分配和回收都具有確定性.因此,GC垃圾回收主要集中在堆和方法區,運行期間,內存的分配和回收都是動態的

3.1.判斷對象存活

  • 常規方法分:引用計數法和可達性分析法
  • 引用計數法:給每個對象添加一個引用計數器,每當引用它時計數器加1,引用釋放時減1,為0時可以回收(java虛擬機沒有使用,沒有解決循環引用的問題)
  • 可達性分析法:GC Root對象(如系統類加載器,棧中的對象,處于激活狀態的線程)作為起點,向下搜索,與其相連的存活,沒有任何一條與GC Root相連的不可用
可達性分析法

3.2.垃圾回收算法

3.2.1.標記清除算法

  • 包含"標記"和"清除"兩個階段,首先標記所有需要回收的對象,標記完成后統一回收
編輯清除算法

缺點:標記和清除效率不高,標記清除后會產生大量不連續的內存碎片,后續對象需要較大內存時會應無法找到足夠的連續內存空間而提前觸發垃圾收集動作

3.2.2.復制算法

  • 將內存容量劃分為大小相等的兩塊,只使用其中的一塊,沒有足夠內存空間時,將還存活的對象復制到另一塊,然后清理掉這一塊的內存
復制算法
  • 優勢:對半回收時,內存分配不用考慮內存碎片的情況,只需移動堆頂指針,按順序分配內存即可,簡單,高效
  • 劣勢:可用內存縮小為1半,性價比低,新生對象存活率高時,復制工作效率低
堆內存分配結構圖
  • GC過程中,當Eden區滿時,還存活的對象會復制到其中的一個Survivor區(如果Survivor區沒有足夠的內存時,會進入老年代),回收時會將Eden和Survivor區還存活的對象,復制到另一個Survivor區,然后清理Eden和用過的survivor區
  • 在GC的整個過程中,由于Eden是對象創建和回收的主要區域,所以采用8:1:1的比例來分配內存;對象每經歷一次復制,年齡加1,達到晉升年齡的閾值后轉移到老年代(老年代采用的是標記整理算法)

3.2.3.標記整理算法

標記過程與"標記清除算法"一樣,然后讓所有存活的對象都向一端移動,然后清理掉邊界外的內存

標記整理算法

這算法既沒有浪費50%的內存,也不會因對象存活率高導致效率低下(老年代采用該算法)

3.2.4.分代收集算法

將Java的堆內存邏輯上分為兩塊,新生代和老年代,針對不同的存貨周期,不同大小的對象采用不同的垃圾回收策略

新生代中大多數對象的存活時間都是瞬間的,只有少量對象存活,復制少量對象即可完成清理,即采用復制算法

老年代中的對象存活率高,也不需要額外的而輔助內存,因此采用標記整理算法

3.3.垃圾收集器

Java7和Java8默認使用的是Parallel,Java9和Java10使用的是G1

3.3.1.Parallel收集器

  • 新生代使用復制算法
  • 老年代使用標記整理算法
  • -XX:+UseParallelGC,使用Parallel收集器+老年代串行
  • -XX:+UseParallel收集器+老年代并行


    Parallel收集過程

3.3.2.GMS收集器

  • Concurrent Mark Sweep 并發標記清除(應用線程和GC線程交替執行)
  • 使用標記清除算法
  • 并發階段會降低吞吐量(停頓時間減少,吞吐量降低)
  • 老年代收集器(新生代使用ParNew)
GMS收集過程
  • 1.初始標記(會產生全局停頓)-根可以直接關聯到的對象,速度較快
  • 2.并發標記(和用戶線程一起)-標記過程,標記全部對象
  • 3.重新標記(會產生全局停頓)-并發標記時,用戶線程依然運行,正式清理前,再做修正
  • 4.并發清除(和用戶線程一起)-基于標記結果,直接清理對象

3.3.3.G1收集器

最新前沿成果之一,將替換掉JDK1.5中的CMS收集器

  • G1收集器的運作大致可劃分為以下幾個步驟:初始標記(Initial Marking),并發標記(Concurrent Marking),最終標記(Final Marking),篩選回收(Live Data Counting and Evacuation),與CMS流程很相似
  • 使用G1收集器時,Java堆的內存布局與其他收集器有很大差別,它將整個Java堆劃分為多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔閡了,它們都是一部分(可以不連續)Region的集合

4.總結

JVM有良好的的自動內存管理機制,但在某些極端情況下也許開發者妥善處理,方便JVM更好的管理內存.學習此章只需結合場景理解不同的收集算法即可,都是些概念方面的知識點


參考博客:
https://www.choupangxia.com/2019/10/20/interview-jvm-gc-01/
https://www.choupangxia.com/2019/10/25/interview-jvm-gc-03/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。