垃圾回收算法你不知道的奧秘

程序員小迷 2024-05-03 12:58:57

一、對象回收判定方法

1.引用計數法(PHP語言在用):快,方便,實現簡單,缺點:對象相互引用時,很難判斷對象是否該回收。

2.可達性分析(Java語言在用)

通過一系列的稱爲"GC Roots"的對象作爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的,可以被回收。

能作爲GC Roots的對象包括下面幾種:

1) 方法區中常量引用的對象。

2) 方法區中類靜態屬性引用的對象。

3) 虛擬機棧(棧幀中的本地變量表)中引用的對象。

4) 本地方法棧中JNI(即Native方法)引用的對象。

二、垃圾回收算法分類

1.Serial/Serial Old

最古老的,單線程,獨占式,成熟,適合單CPU 服務器。

2.ParNew

和Serial基本沒區別,唯一的區別:多線程,多CPU的,停頓時間比Serial少。

ParNew垃圾收集器是Serial收集器的多線程版本。

3.Parallel Scavenge

吞吐量優先收集器。 新生代,複制算法。 並行的多線程收集器。 類似ParNew,更加關注吞吐量,達到一個可控制的吞吐量。 Server級別多CPU機器上的默認GC方式,主要適合後台運算不需要太多交互的任務。

4.Parallel Old

老年代,標記整理算法。 並行的多線程收集器。

是Parallel Scavenge收集器的老年代版本,爲了配合Parallel Scavenge的面向吞吐量的特性而開發的對應組合。

在注重吞吐量以及CPU資源敏感的場合采用 。

5.CMS

用于老年代,標記清除算法。 並行與並發收集器。

盡可能的縮短垃圾收集時用戶線程停止時間。缺點在于:

1)內存碎片 。

2)需要更多cpu資源 。

3)浮動垃圾問題,需要更大的堆空間 。 用于重視服務的響應速度、系統停頓時間和用戶體驗的互聯網網站或者B/S系統。互聯網後端目前CMS是主流的垃圾回收器。

6.G1

跨新生代和老年代。標記整理 + 化整爲零 。 並行與並發收集器 。 JDK1.7才正式引入,采用分區回收的思維,基本不犧牲吞吐量的前提下完成低停頓的內存回收。可預測的停頓是其最大的優勢。 面向服務端應用的垃圾回收器,目標爲取代CMS。

並行與並發:G1能充分利用多CPU、多核環境下的硬件優勢,使用多個CPU(CPU或者CPU核心)來縮短Stop The World停頓的時間,部分其他收集器原本需要停頓Java線程執行的GC動作,G1收集器仍然可以通過並發的方式讓Java程序繼續執行。

分代收集:與其他收集器一樣,分代概念在G1中依然得以保留。雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但它能夠采用不同的方式去處理新創建的對象和已經存活了一段時間、熬過多次GC的舊對象以獲取更好的收集效果。

空間整合:與CMS的"標記—清理"算法不同,G1從整體來看是基于"標記—整理"算法實現的收集器,從局部(兩個Region之間)上來看是基于"複制"算法實現的,但無論如何,這兩種算法都意味著G1運作期間不會産生內存空間碎片,收集後能提供規整的可用內存。這種特性有利于程序長時間運行,分配大對象時不會因爲無法找到連續內存空間而提前觸發下一次GC。

內存布局:在G1之前的其他收集器進行收集的範圍都是整個新生代或者老年代,而G1不再是這樣。使用G1收集器時,Java堆的內存布局就與其他收集器有很大差別,它將整個Java堆劃分爲多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續)的集合。

1) 新生代GC

回收Eden區和Survivor區,回收後,所有Eden區被清空,存在一個Survivor區保存了部分數據。老年代區域會增多,因爲部分新生代的對象會晉升到老年代。

2) 並發標記周期

初始標記:短暫,僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,産生一個全局停頓,都伴隨有一次新生代的GC。

根區域掃描:掃描Survivor區可以直接到達的老年代區域。

並發標記階段:掃描和查找整個堆的存活對象,並標記。

重新標記:會産生全局停頓,對並發標記階段的結果進行修正。

獨占清理:會産生全局停頓,對GC回收比例進行排序,供混合收集階段使用。

並發清理:識別並清理完全空閑的區域,並發進行。

3) 混合收集

對含有垃圾比例較高的Region進行回收。

G1當出現內存不足的的情況,也可能進行的Full GC回收。

G1中重要的參數:

-XX:MaxGCPauseMillis 指定目標的最大停頓時間,G1嘗試調整新生代和老年代的比例,堆大小,晉升年齡來達到這個目標時間。

-XX:ParallelGCThreads:設置GC的工作線程數量。

7.未來的垃圾回收器ZGC(Z Garbage Collector)

ZGC通過技術手段把stw(Stop The World)的情況控制在僅有一次,就是第一次的初始標記才會發生,這樣也就不難理解爲什麽GC停頓時間不隨著堆增大而上升了,再大也是通過並發的時間去回收了。

關鍵技術:

1) 有色指針(Colored Pointers)

2) 加載屏障(Load Barrier)

存儲在對象字段中的對象引用被實現爲有色指針。存儲在 JVM 堆棧中的對象引用在硬件堆棧或 CPU 寄存器中實現爲無色指針。讀屏障和存儲屏障控制有色指針和無色指針之間的轉換。

三、垃圾回收算法配置

-XX:+UseSerialGC 新生代和老年代都用串行收集器。

-XX:+UseParNewGC 新生代使用ParNew,老年代使用Serial Old。

-XX:+UseParallelGC 新生代使用Paraller Scavenge GC,老年代使用Serial Old。

-XX:+UseConcMarkSweepGC  新生代使用ParNew,老年代的用CMS。

-XX:+UseG1GC 使用G1垃圾回收算法。

微風不燥,陽光正好,你就像風一樣經過這裏,願你停留的片刻溫暖舒心。

我是程序員小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等編程技術的技巧經驗分享),若作品對您有幫助,請關注、分享、點贊、收藏、在看、喜歡,您的支持是我們爲您提供幫助的最大動力。

歡迎關注。助您在編程路上越走越好!

0 阅读:7

程序員小迷

簡介:致力于Android、C等編程技術的技巧經驗分享