探索JVM的垃圾回收(堆記憶體)

快乐的总统95發表於2024-10-04

Java 8+

-

序章

在 C/C++ 語言中,程式設計師自己分配記憶體、回收記憶體,不存在垃圾回收一說。

而在 Java 中,記憶體分配 絕大多數 是 JVM 的工作——棧記憶體、堆記憶體、永久代/元空間 等。ben釋出於部落格園

記憶體分配了就完了嗎?不。JVM 執行時 的 記憶體不是無限的,受制於 程式設計師配置、系統記憶體上限,因此,在有限的記憶體中,還要進行 垃圾回收。

棧記憶體、永久代/元空間 不需要 垃圾回收,垃圾回收的重點在於——堆記憶體。(本句 存疑,畢竟,不是100%瞭解 Java Memory Model、垃圾回收 等,官文、原始碼沒看過呢。)

近期看過幾篇 JVM、垃圾回收的博文,特總結記錄於此(總結了,才好提高嘛)。

ben釋出於部落格園

堆記憶體結構:(年輕代(Eden;Survivor(To;From;));老年代)

假設堆記憶體有50MB,預設情況下,其不同區分配的記憶體為:

探索JVM的垃圾回收(堆記憶體)

修改配置調整(調優)後,比例應該就不同了。ben釋出於部落格園

HotSpot Virtual Machine Garbage Collection Tuning Guide

https://docs.oracle.com/en/java/javase/21/gctuning/preface.html

#可下載pdf

官方文件,介紹了 HotSpot VM (JVM 的 Oracle 實現) 的 垃圾回收調優,涉及 各種 垃圾回收器。

探索JVM的垃圾回收(堆記憶體)

當然,Java 8 也有:ben釋出於部落格園

https://docs.oracle.com/javase/8/

探索JVM的垃圾回收(堆記憶體)

不過,沒有 PDF 下載了。

注,上面兩個文件作者也是第一次開啟,還沒細看。

垃圾回收演算法

》引用計數法:

存在迴圈引用問題。

英文:Reference Counting

》標記-清除演算法 Mark-Sweep

引用:首先標記出所有不需要回收的物件,在標記完成後統一回收掉所有沒有被標記的物件。
它是最基礎的收集演算法,後續的演算法都是對其不足進行改進得到。
效率問題、空間問題(碎片)。

#參考資料2

英文:Mark-Sweep

》複製演算法:

浪費記憶體。

不適合老年代。

英文:Copying Algorithm

》標記-整理演算法 Mark-Compact

另名,標記-壓縮演算法

引用:是根據 老年代的特點 提出的一種標記演算法,標記過程仍然與“標記-清除”演算法一樣,但後續步驟不是直接對可回收物件回收,

而是 讓所有存活的物件向一端移動,然後直接清理掉端邊界以外的記憶體。

#參考資料2

英文:Mark-Compact

》分代收集演算法 Generational Collection

引用:當前虛擬機器的垃圾收集都採用分代收集演算法,這種演算法沒有什麼新的思想,只是根據物件存活週期的不同將記憶體分為幾塊。

#參考資料2 文中還有 更多介紹。

引用:"分代收集演算法基於物件的存活時間,將堆記憶體分為幾代:

年輕代(Young Generation)、年老代(Old Generation)和永久代(Permanent Generation)。

各代使用不同的收集演算法。"

#參考資料6

英文:Generational Collection

說明,不同的垃圾回收演算法 可能是 來自一篇篇 學術論文

垃圾回收器

》Serial:

單執行緒垃圾收集。ben釋出於部落格園

》ParNew:

Serial 收集器的多執行緒版本。

新生代採用標記-複製演算法,老年代採用標記-整理演算法。

英文:Par 是 Parallel 的縮寫。

》Parallel Scavenge

引用:也是使用標記-複製演算法的多執行緒收集器,它看上去幾乎和 ParNew 都一樣。

引用:Parallel Scavenge 收集器關注點是吞吐量(高效率的利用 CPU)。

引用:新生代採用標記-複製演算法,老年代採用標記-整理演算法。

引用:JDK1.8 預設使用的是 Parallel Scavenge + Parallel Old(下面)

如果指定了-XX:+UseParallelGC 引數,則預設指定了-XX:+UseParallelOldGC,可以使用-XX:-UseParallelOldGC 來禁用該功能。

英文:Scavenge(英 [ˈskævɪndʒ] vt.& vi.清除汙物,打掃; (在廢物中)尋覓; (動物)食腐肉)

》Serial Old:

Serial 收集器的老年代版本。

》Parallel Old

Parallel Scavenge 收集器的老年代版本。ben釋出於部落格園

》CMS:

引用:CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。它非常符合在注重使用者體驗的應用上使用。

引用:HotSpot 虛擬機器第一款真正意義上的【併發收集器】(不是 並行!)。

注意,出現了 Safepoint 概念

已廢棄。

2020年3月:JDK14釋出,剔除了CMS收集器。

引用:CMS 垃圾回收器在 Java 9 中已經被標記為過時(deprecated),並在 Java 14 中被移除。

》G1

引用:G1 (Garbage-First) 是一款面向伺服器的垃圾收集器,主要針對配備多顆處理器及大容量記憶體的機器. 以極高機率滿足 GC 停頓時間要求的同時,還具備高吞吐量效能特徵。

引用:從 JDK9 開始,G1 垃圾收集器成為了預設的垃圾收集器

》ZGC

這款收集器的名字就叫作 Z Garbage Collector。ben釋出於部落格園

引用:

ZGC 在 Java11 中引入,處於試驗階段。
ZGC 在 Java15 已經可以正式使用了。

官網:

1、https://wiki.openjdk.org/display/zgc/Main

探索JVM的垃圾回收(堆記憶體)

2、https://docs.oracle.com/en/java/javase/21/gctuning/z-garbage-collector.html

Quote:

The Z Garbage Collector (ZGC) is a scalable low latency garbage collector.

ZGC performs all expensive work concurrently, without stopping the execution of application threads for more than a millisecond.

It is suitable for applications which require low latency.

Pause times are independent of the heap size that is being used.

ZGC works well with heap sizes from a few hundred megabytes to 16TB.

》ShenandoahGC:

引用:Shenandoah GC 是一種低停頓的垃圾回收器,旨在解決傳統垃圾回收器在大型堆上產生的停頓時間過長的問題。它是 OpenJDK 專案的一部分,並在 Java 12 中首次引入。

博文:Java 21 將放棄分代 Shenandoah GC

釋出於 2023-06-17 23:22:06

https://cloud.tencent.com/developer/article/2296640

注,剛聽說,就廢棄了?ben釋出於部落格園

英文:Shenandoah([地名] [美國] 謝南多厄; [電影]烽火田園)

選擇垃圾回收器的考慮因素

堆記憶體 大小。

停頓時間(Full GC 導致的 STW(Stop The World)):使用者執行緒的停頓時間。

吞吐量:高效率的利用 CPU。ben釋出於部落格園

Minor GC vs Major GC vs Full GC

在 官文 HotSpot Virtual Machine Garbage Collection Tuning Guide 中可以搜尋到 minor gc, major gc, full gc 等概念。

注,下面是在 Release 21(Java 21) 的 pdf文件中 檢索。

搜尋:minor

探索JVM的垃圾回收(堆記憶體)

Quote: When the young generation fills up, it causes a minor collection in which only the young generation is collected; garbage in other generations isn't reclaimed.

Quote: Eventually, the old generation fills up and must be collected, resulting in a major collection, in which the entire heap is collected.

探索JVM的垃圾回收(堆記憶體)

搜尋 full:ben釋出於部落格園

探索JVM的垃圾回收(堆記憶體)

引用:

Minor GC 是 清理 新生代中的Eden區, Survivor區滿時不會觸發 ; Major GC 是 清理 老年代 ; Full GC 是 清理整個堆和方法區,包括 年輕代、老年代和方法區。

來自 參考資料#4

ben釋出於部落格園

注,官網文件 作者還未細看,資訊或許不準確,請注意。

小結

Safepoint 的引入,實現了 併發垃圾收集。

Java 8 預設使用 Parallel Scavenge + Parallel Old。

Java 9+ 預設使用 G1(Garbage First)。

目前使用的是 Java 17,預設G1,也可以透過引數 -XX:+UseZGC 使用 ZGC。

列印GC執行 的引數:-XX:+PrintGCDetails

2024年,重點關注 G1、ZGC 兩種,尤其是 預設的 G1。至於 比 Java 17 更高的版本,目前還沒用過。

ben釋出於部落格園

---END---

引用了不少其它博文的語句,如有冒犯,請通知作者刪除

水平非常有限,如有錯漏,請不吝告知

謝謝。

本文連結:

https://www.cnblogs.com/luo630/p/18445951

參考資料

1、1.大白話帶你認識 JVM
https://javaguide.cn/java/jvm/jvm-intro.html

2、JVM垃圾回收詳解(重點)
https://javaguide.cn/java/jvm/jvm-garbage-collection.html

3、G1、ZGC、ShenandoahGC 高效能收集器深入剖析

Java全棧架構師的文章 - 知乎
https://zhuanlan.zhihu.com/p/624386102
釋出於 2023-04-24 10:13

4、Minor GC、Major GC、Full GC的區別
釋出於 2021-07-21 10:46:46

https://cloud.tencent.com/developer/article/1850327

5、官方文件:HotSpot Virtual Machine Garbage Collection Tuning Guide

6、深入理解Java的垃圾回收機制(GC)實現原理
2024-06-14
https://developer.aliyun.com/article/1537550

7、探索JVM垃圾回收演算法:選擇適合你應用的最佳GC策略
2024-08-16
https://developer.aliyun.com/article/1588394

8、

ben釋出於部落格園

ben釋出於部落格園

相關文章