關(guān)于jvm的垃圾回收器以及觸發(fā)full gc的場景
jvm的垃圾回收器以及觸發(fā)full gc的場景
JVM(Java虛擬機)的垃圾回收器有很多種,主要包括以下幾種:
- Serial收集器:串行收集器是最古老、最穩(wěn)定的收集器。它使用單個線程進行垃圾收集工作,在進行垃圾回收時會暫停所有用戶線程。
- ParNew收集器:ParNew是Serial收集器的多線程版本,也被稱為“并行年輕代收集器”,可以與CMS收集器配合使用。
- Parallel收集器:Parallel收集器是一種多線程并行的垃圾收集器,用于新生代和老年代的回收。
- CMS收集器:CMS(Concurrent Mark-Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,主要用于老年代的垃圾回收。
- G1收集器:G1(Garbage-First)收集器是一種面向服務端應用的垃圾收集器,逐步取代CMS收集器,具有更可控的停頓時間和高效的并發(fā)能力。
除了上述列出的垃圾回收器之外,還有其他一些實驗性質(zhì)或特定用途的收集器,如ZGC(Z Garbage Collector)和Shenandoah等。
不同的垃圾回收器適用于不同的場景和需求,開發(fā)人員可以根據(jù)應用的特點選擇合適的垃圾回收器來優(yōu)化性能。
Full GC(Full Garbage Collection)是Java中一種對整個堆內(nèi)存進行清理和整理的操作,它會停止應用程序的所有線程,包括Young Generation和Old Generation的內(nèi)存區(qū)域都會被掃描和回收。
Full GC通常發(fā)生在以下幾種情況下:
- 當Eden區(qū)滿了,并且觸發(fā)Minor GC后,存活對象無法全部晉升到Survivor區(qū)時,會將剩余的對象直接放入老年代,如果老年代空間不足以容納這些對象,就會觸發(fā)Full GC。
- 在Old Generation中進行大對象分配時,如果無法找到足夠的連續(xù)空間來分配該大對象,也會觸發(fā)Full GC。
- 永久代(在JDK 8之前)或元空間(在JDK 8及更高版本)內(nèi)存不足時,可能會觸發(fā)Full GC。
- 顯式調(diào)用System.gc()方法,通知虛擬機執(zhí)行Full GC。
- CMS(Concurrent Mark-Sweep)垃圾收集器在并發(fā)標記階段出現(xiàn)"Concurrent Mode Failure"時,會導致一次Full GC。
需要注意的是,F(xiàn)ull GC的頻繁發(fā)生會影響系統(tǒng)的性能,因此在實際開發(fā)中需要合理設置堆內(nèi)存大小、優(yōu)化程序設計以盡量減少Full GC的發(fā)生。
jvm垃圾回收面試題
如何判斷對象是否死亡(兩種方法)
引用計數(shù)法對象 + 一個引用計數(shù)器,引用 +1;失效 -1;任何時候計數(shù)器為 0 的對象就是不可能再被使用的。
這個方法實現(xiàn)簡單,效率高,但是目前主流的虛擬機中并沒有選擇這個算法來管理內(nèi) 存,其最主要的原因是它很難解決對象之間相互循環(huán)引用的問題。
可達性分析算法 “GC Roots” 對象為起點,從這些節(jié)點開始向下搜索,節(jié)點所走過的路徑稱為引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證明此對象是不可用的。
可作為 GC Roots 的對象包括下面幾種:
- 虛擬機棧(棧幀中的本地變量表)中引用的對象
- 本地方法棧(Native 方法)中引用的對象
- 方法區(qū)中類靜態(tài)屬性引用的對象
- 方法區(qū)中常量引用的對象
- 所有被同步鎖持有的對象
簡單的介紹一下強引用、軟引用、弱引用、虛引用
(虛引用與軟引用和弱引用的區(qū) 別、使用軟引用能帶來的好處)。
JDK1.2 前,傳統(tǒng)引用定義:reference 類型數(shù)據(jù)存儲數(shù)值代表另一塊內(nèi)存的起始地址。
JDK1.2 后,引用擴充,分為強、軟、弱、虛四種(引用強度逐漸減弱)
強引用,垃圾回收器不回收。當內(nèi)存不足,Java 虛擬機拋出 OutOfMemoryError 錯誤
軟引用,內(nèi)存空間足夠,不回收。內(nèi)存不足,回收。可實現(xiàn)內(nèi)存敏感的高速緩存。 如果軟引用的對象被垃圾回收,jvm把軟引用加入關(guān)聯(lián)引用隊列。
軟引用加速垃圾回收,維護系統(tǒng)安全,防止(OOM)等問題的產(chǎn)生。
弱引用,弱、軟區(qū)別——弱對象生命周期更短。不管內(nèi)存空間是否足夠,都回收。
虛引用,虛引用不決定對象生命周期。在任何時候可能被垃圾回收。虛引用跟蹤對象被垃圾回收的活動。
虛引用與軟引用和弱引用的區(qū)別: 虛引用必須和引用隊列 (ReferenceQueue)聯(lián)合使用。
如何判斷一個常量是廢棄常量
1. JDK1.7 之前,運行時常量池 (字符串常量池)→→方法區(qū), 方法區(qū)實現(xiàn)永久代
2. JDK1.7 字符串常量池→→堆, 運行時常量池→→方法區(qū)。
3. JDK1.8 元空間 取代 永久代, 字符串常量池→→堆, 運行時常量池→→方法區(qū),方法區(qū)實現(xiàn)元空間
字符串常量池中存在字符串 "abc",當前沒有任何 String 對象引用,就說明常量 "abc" 就是廢棄常量,如果這時發(fā)生內(nèi)存回收,"abc" 被清理。
如何判斷一個類是無用的類
- 該類所有實例被回收。
- ClassLoader 被回收。
- java.lang.Class 對象不被引用,無法通過反射訪問。
垃圾收集有哪些算法,各自的特點?
標記-清除/復制/整理、分代收集
標記-清除算法“標記”出所有不回收對象,“清除”回收沒有被標記對象。
1. 效率問題 2. 空間問題(標記清除后會產(chǎn)生大量不連續(xù)的碎片)
標記-復制算法內(nèi)存分為兩塊, 每次用一塊。一塊用完,將存活對象復制到另一塊, 然后清理使用的空間。每次對內(nèi)存一半回收。
標記-整理算法“標記”出所有不回收對象,所有存活對象向一端移動,清理端邊界以外內(nèi)存。
分代收集算法根據(jù)對象存活周期不同將內(nèi)存分為幾塊。一般將 java 堆分為新生代和老年代。
比如新生代中,每次收集都會有大量對象死去,選擇”標記-復制“算法,付出少量對象的復制成本。老年代的對象存活率比較高,必須選擇“標記-清除”或“標記-整理”算法進行垃圾收集。
HotSpot 為什么要分為新生代和老年代?
常見的垃圾回收器有哪些?
Serial 收集器一個單線程收集器。新生代采用標記-復制算法,老年代采用標記-整理算法。簡單高效。適合Client 模式下的虛擬機
ParNew 收集器是 Serial 收集器的多線程版本,能與 CMS 收集器工作。適合Server 模式下的虛擬機
Parallel Scavenge 收集器Parallel Scavenge 收集器關(guān)注點是吞吐量(運行用戶代碼時間與 CPU 總消耗時間的比值)。CMS 等垃圾收集器 關(guān)注點是用戶線程的停頓時間(提高用戶體驗)。
Serial Old 收集器 Serial 收集器的老年代版本,一個單線程收集器。兩大用途:JDK1.5 以前與 Parallel Scavenge 收集器搭配使用,另一種用途是作為 CMS 收集器的后備方案。
Parallel Old 收集器 Parallel Scavenge 收集器的老年代版本。使用多線程和“標記-整理”算法。在注重吞吐量 以及 CPU 資源的場合,優(yōu)先考慮 Parallel Scavenge 收集器和 Parallel Old 收集 器。
CMS(Concurrent Mark Sweep)收集器一種獲取最短回收停頓時間為目標的收集器。 第一款并發(fā)收集器,第一次實現(xiàn)垃圾收集線程與用戶線程同時工作。優(yōu)點:并發(fā)收集、低停頓。缺點:CPU 資源敏感; 無法處理浮動垃圾; “標記-清除”算法結(jié)束時產(chǎn)生大量空間碎片。
- 初始標記: 暫停所有線程,記錄 root 相連對象
- 并發(fā)標記: 同時開啟 GC 和用戶線程,閉包記錄可達對象。
- 重新標記: 修正并發(fā)標記期間標記產(chǎn)生變動的標記記錄
- 并發(fā)清除: 開啟用戶線程,同時 GC 線程對未標記的區(qū)域做清掃。
G1 (Garbage-First)一款面向服務器的垃圾收集器。高概率滿足 GC 停頓時間要求,高吞吐量性能特征。被視為 JDK1.7 中 HotSpot 虛擬機的一個重要進化特征。
- 并行與并發(fā):G1 充分利用 CPU、多核環(huán)境,縮短 Stop-The-World 停頓時間。
- 分代收集:保留分代概念。
- 空間整合:G1 整體“標記-整理”;局部“標記-復制”。
- 可預測的停頓:G1 除了追求低停頓外,建立可預測的停頓時間模型。
G1 收集器的運作: 初始標記 并發(fā)標記 最終標記 篩選回收
G1 收集器在后臺維護了一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先選擇回收價值 最大的 Region(這也就是它的名字 Garbage-First 的由來) 。
ZGC 收集器 與 CMS 中的 ParNew 和 G1 類似,ZGC 也采用標記-復制算法,不過 ZGC 對該算法做了重大改進。
介紹一下 CMS,G1 收集器。 Minor Gc 和 Full GC 有什么不同呢?
部分收集 (Partial GC):
新生代收集(Minor GC / Young GC):只對新生代進行垃圾收集;老年代收集(Major GC / Old GC):只對老年代進行垃圾收集。需要注意的是 Major GC 在有的語境中也用于指代整堆收集;混合收集(Mixed GC):對整個新生代和部分老年代進行垃圾收集。
整堆收集 (Full GC):收集整個 Java 堆和方法區(qū)。
Minor GC觸發(fā)條件:當Eden區(qū)滿時,觸發(fā)Minor GC。
Full GC觸發(fā)條件:
- 通過Minor GC后進入老年代的平均大小大于老年代的可用內(nèi)存。如果發(fā)現(xiàn)統(tǒng)計數(shù)據(jù)說之前Minor GC的平均晉升大小比目前old gen剩余的空間大,則不會觸發(fā)Minor GC而是轉(zhuǎn)為觸發(fā)full GC。
- 老年代空間不夠分配新的內(nèi)存(或永久代空間不足,但只是JDK1.7有的,這也是用元空間來取代永久代的原因,可以減少Full GC的頻率,減少GC負擔,提升其效率)。
- 由Eden區(qū)、From Space區(qū)向To Space區(qū)復制時,對象大小大于To Space可用內(nèi)存,則把該對象轉(zhuǎn)存到老年代,且老年代的可用內(nèi)存小于該對象大小。
- 調(diào)用System.gc時,系統(tǒng)建議執(zhí)行Full GC,但是不必然執(zhí)行。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring3 MVC請求參數(shù)獲取的幾種方法小結(jié)
本篇文章主要介紹了Spring3 MVC請求參數(shù)獲取的幾種方法小結(jié),非常具有實用價值,需要的朋友可以參考下。2017-03-03SpringBoot接口調(diào)用之后報404問題的解決方案
這篇文章主要介紹了SpringBoot接口調(diào)用之后報404問題的解決方案,具有很好的參考價值,希望對大家有所幫助。2021-06-06淺談Java開發(fā)架構(gòu)之領(lǐng)域驅(qū)動設計DDD落地
DDD(Domain-Driven Design 領(lǐng)域驅(qū)動設計)是由Eric Evans最先提出,目的是對軟件所涉及到的領(lǐng)域進行建模,以應對系統(tǒng)規(guī)模過大時引起的軟件復雜性的問題2021-06-06springboot用戶數(shù)據(jù)修改的詳細實現(xiàn)
用戶管理功能作為所有的系統(tǒng)是必不可少的一部分,下面這篇文章主要給大家介紹了關(guān)于springboot用戶數(shù)據(jù)修改的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2022-04-04SpringBoot實現(xiàn)多數(shù)據(jù)源的實戰(zhàn)案例
這篇文章主要介紹了SpringBoot實現(xiàn)多數(shù)據(jù)源的實戰(zhàn)案例,文中通過示例代碼和圖文展示介紹的非常詳細,對大家的學習或工作有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2024-01-01