JVM垃圾回收器全面解析與G1深度探秘及四種引用詳解
- JVM虛擬機(七):JVM垃圾回收器全面解析與G1深度探秘及四種引用詳解
- 一、JVM有哪些垃圾回收器
- 1. Serial回收器
- 2. ParNew回收器
- 3. Parallel Scavenge回收器
- 4. Serial Old回收器
- 5. Parallel Old回收器
- 6. CMS(Concurrent Mark Sweep)回收器
- 7. G1(Garbage-First)回收器
- 二、詳細聊一下G1垃圾回收器
- 3.6.1 概述
- 3.6.2 Young Collection(年輕代垃圾回收)
- 3.6.3 Young Collection + Concurrent Mark(年輕代垃圾回收 + 并發標記)
- 3.6.4 Mixed Collection(混合垃圾回收)
- 三、強引用、軟引用、弱引用、虛引用的區別
- 3.7.1 強引用(Strong Reference)
- 3.7.2 軟引用(Soft Reference)
- 3.7.3 弱引用(Weak Reference)
- 3.7.4 虛引用(Phantom Reference)
JVM虛擬機(七):JVM垃圾回收器全面解析與G1深度探秘及四種引用詳解
一、JVM有哪些垃圾回收器
在Java虛擬機(JVM)中,垃圾回收器負責自動管理內存,回收不再使用的對象所占用的內存空間。不同的垃圾回收器具有不同的特點和適用場景,以下是常見的JVM垃圾回收器:
1. Serial回收器
- 特點:單線程垃圾回收器,在進行垃圾回收時,會暫停所有用戶線程(Stop-The-World,STW)。它簡單高效,對于單線程環境或小型應用程序有較好的性能表現。
- 適用場景:Client模式下的小型應用,對內存要求不高,單核CPU環境。
2. ParNew回收器
- 特點:Serial回收器的多線程版本,允許多個線程同時進行垃圾回收,同樣會產生STW。它常與CMS回收器配合使用,是Server模式下新生代回收的常用選擇之一。
- 適用場景:Server模式,多核CPU環境,與CMS配合時的新生代回收。
3. Parallel Scavenge回收器
- 特點:關注吞吐量的垃圾回收器,通過最大化吞吐量來提高程序的運行效率。它也是多線程回收器,可通過參數控制吞吐量目標。
- 適用場景:后臺任務、對響應時間要求不高但重視吞吐量的應用,如批量數據處理。
4. Serial Old回收器
- 特點:Serial回收器的老年代版本,單線程回收,使用標記-整理算法。通常作為其他回收器的后備方案,在JVM內存較小、單核環境下仍有一定應用。
- 適用場景:與Serial回收器配合,或作為Parallel Scavenge老年代回收的后備。
5. Parallel Old回收器
- 特點:Parallel Scavenge的老年代版本,多線程,采用標記-整理算法,提供與Parallel Scavenge類似的吞吐量優先特性。
- 適用場景:注重吞吐量的應用,老年代回收,與Parallel Scavenge配合。
6. CMS(Concurrent Mark Sweep)回收器
- 特點:以獲取最短回收停頓時間為目標的回收器,采用標記-清除算法。它能在垃圾回收時與用戶線程并發執行部分操作,減少STW時間。
- 優點:響應速度快,適合對響應時間要求高的應用,如Web應用。
- 缺點:會產生內存碎片,并發階段可能因用戶線程繼續運行導致重新標記,且對CPU資源敏感。
- 適用場景:B/S架構等對響應時間敏感的應用。
7. G1(Garbage-First)回收器
- 特點:新一代垃圾回收器,將堆內存劃分為多個大小相等的Region,采用分代收集思想,但不再有固定的新生代和老年代。它能更精確地控制垃圾回收的停頓時間,同時兼顧吞吐量和響應時間。
- 適用場景:大內存、多處理器環境,對停頓時間有嚴格要求的應用,是JDK 9及以上的默認回收器。
二、詳細聊一下G1垃圾回收器
3.6.1 概述
G1(Garbage-First)回收器是一種面向服務器的垃圾回收器,旨在滿足高吞吐量和低停頓時間的需求。與傳統回收器不同,G1將堆內存劃分為大量大小相等的Region(區域),每個Region可以動態地扮演新生代或老年代的角色。G1通過維護一個優先列表,每次根據允許的停頓時間優先回收垃圾最多的Region,這也是其名稱“Garbage-First”的由來。這種設計使得G1能更靈活地控制垃圾回收的停頓時間,同時提高內存的利用率和回收效率。
3.6.2 Young Collection(年輕代垃圾回收)
- 回收過程:當新生代的Eden區填滿時,觸發Young Collection。G1采用復制算法,將Eden區和Survivor區中存活的對象復制到另一個空的Survivor區或晉升到老年代(如果對象年齡達到閾值)。此時會產生STW,但由于新生代對象存活率通常較低,復制操作的開銷相對較小。
- 特點:快速處理新生代大量短生命周期的對象,通過多線程并行執行,減少回收時間。
3.6.3 Young Collection + Concurrent Mark(年輕代垃圾回收 + 并發標記)
- 并發標記階段:
- 初始標記(Initial Mark):STW,標記GC Roots直接引用的對象,時間很短。
- 并發標記(Concurrent Mark):與用戶線程并發執行,從GC Roots開始遍歷對象圖,標記存活的對象。
- 最終標記(Final Mark):STW,處理并發標記階段遺留的少量對象,確保標記準確。
- 篩選回收(Live Data Counting and Evacuation):計算每個Region的存活對象和可回收空間,為混合回收做準備。
- 與Young Collection的配合:在年輕代回收后,通過并發標記確定老年代中哪些Region含有較多垃圾,為后續的混合回收提供依據。
3.6.4 Mixed Collection(混合垃圾回收)
- 回收過程:G1根據篩選回收階段的統計信息,選擇垃圾比例較高的老年代Region,結合新生代Region一起回收。回收時采用復制算法,將存活對象復制到空的Region中,從而清理掉垃圾較多的Region。
- 特點:在控制停頓時間的前提下,逐步回收老年代的垃圾,避免老年代內存碎片化,同時提高整體內存的利用率。
三、強引用、軟引用、弱引用、虛引用的區別
3.7.1 強引用(Strong Reference)
- 定義:程序中最常見的引用方式,如
Object obj = new Object();
,obj就是一個強引用。 - 回收時機:只要強引用存在,垃圾回收器永遠不會回收被引用的對象。即使內存不足,JVM也會拋出
OutOfMemoryError
而不會回收強引用對象。 - 應用場景:大多數普通對象的引用,確保對象在需要時始終存在。
3.7.2 軟引用(Soft Reference)
- 定義:通過
SoftReference
類實現,如SoftReference<Object> softRef = new SoftReference<>(new Object());
。 - 回收時機:當內存不足時,垃圾回收器會回收軟引用所引用的對象。軟引用通常用于實現緩存,在內存充足時保留對象,內存緊張時釋放以避免OOM。
- 應用場景:圖片緩存、網頁緩存等,允許在內存不足時釋放非關鍵對象。
3.7.3 弱引用(Weak Reference)
- 定義:通過
WeakReference
類實現,WeakReference<Object> weakRef = new WeakReference<>(new Object());
。 - 回收時機:只要發生垃圾回收,無論內存是否充足,弱引用所引用的對象都會被回收。弱引用的生命周期更短。
- 應用場景:臨時對象、對生命周期要求較短的輔助對象,如哈希表中的弱引用鍵值對,避免內存泄漏。
3.7.4 虛引用(Phantom Reference)
-
定義:通過
PhantomReference
類實現,且必須配合ReferenceQueue
使用,PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), referenceQueue);
。 -
回收時機:虛引用隨時可能被垃圾回收器回收,它主要用于跟蹤對象的垃圾回收狀態,而不是實際引用對象。
-
應用場景:對象回收后的資源釋放等特殊場景,如直接內存的釋放跟蹤。
通過對JVM垃圾回收器的全面了解,尤其是G1回收器的深入剖析,以及四種引用類型的詳細對比,開發者能更好地理解Java內存管理機制,優化程序性能,避免內存相關的問題,編寫出更高效、穩定的Java應用程序。