欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM常用垃圾收集器及GC算法解讀

 更新時間:2024年04月23日 08:35:36   作者:云淡風qin  
這篇文章主要介紹了JVM常用垃圾收集器及GC算法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

GC的種類

1.Minor GC

對象從新生代區(qū)域消失的過程,我們稱之為 “minor GC”。

清理整個YouGen(年輕代)的過程,eden、S0\S1的清理都會由于MinorGC Allocation Failure(YoungGen區(qū)內(nèi)存不足),而觸發(fā)minorGC。

2.Major GC

OldGen區(qū)內(nèi)存不足,觸發(fā)Major GC。

3.Full GC

Full GC 是清理整個堆空間—包括年輕代和永久代。

Full GC 觸發(fā)的場景:

1)手動調(diào)用 System.gc()2)promotion failed (年代晉升失敗,比如eden區(qū)的存活對象晉升到S區(qū)放不下,又嘗試直接晉 升到Old區(qū)又放不下,那么Promotion Failed,會觸發(fā)FullGC)

3)CMS的Concurrent-Mode-Failure 由于CMS回收過程中主要分為四步:

  • 1.CMS initial mark
  • 2.CMS Concurrent mark
  • 3.CMS remark
  • 4.CMS Concurrent sweep。在2中gc線程與用戶線程同時執(zhí)行,那么用戶線程依舊可 能同時產(chǎn)生垃圾,如果這個垃圾較多無法放入預留的空間就會產(chǎn)生CMS-Mode-Failure, 切換 為SerialOld單線程做mark-sweep-compact。

4)新生代晉升的平均大小大于老年代的剩余空間 (為了避免新生代晉升到老年代失敗) 當使用G1,CMS 時,F(xiàn)ullGC發(fā)生的時候 是 Serial+SerialOld。 當使用ParalOld時,F(xiàn)ullGC發(fā)生的時候是ParallNew +ParallOld.

GC的判定

1.引用計數(shù)法:指的是如果某個地方引用了這個對象就+1,如果失效了就-1,當為 0 就會回收但是 JVM 沒有用這種方式,因為無法判定相互循環(huán)引用(A 引用 B,B 引用 A)的情況。

2.引用鏈法(可達性分析/根搜索): 通過一種 GC ROOT 的對象(方法區(qū)中靜態(tài)變量引用的對象等-static 變量)來判斷,如果有一條鏈能夠到達 GC ROOT 就說明該對象不能回首,不能到達 GC ROOT 就說明可以回收

GCRoots有哪些

  • 類,由系統(tǒng)類加載器加載的類。這些類從不會被卸載,它們可以通過靜態(tài)屬性的方式持有對象的引用。
  • 注意,一般情況下由自定義的類加載器加載的類不能成為GC Roots
  • 線程,存活的線程
  • Java方法棧中的局部變量或者參數(shù)
  • JNI方法棧中的局部變量或者參數(shù)
  • JNI全局引用
  • 用做同步監(jiān)控的對象
  • 被JVM持有的對象,這些對象由于特殊的目的不被GC回收。這些對象可能是系統(tǒng)的類加載器,一些重要的異常處理類,一些為處理異常預留的對象,以及一些正在執(zhí)行類加載的自定義的類加載器。但是具體有哪些前面提到的對象依賴于具體的JVM實現(xiàn)。

但是當滿足上述條件時,一個對象比不一定會被回收。

當一個對象不可達 GC Root 時,這個對象并不會立馬被回收,而是出于一個死緩的階段,若要被真正的回收需要經(jīng)歷兩次標記。

  • 如果對象在可達性分析中沒有與 GC Root 的引用鏈,那么此時就會被第一次標記并且進行一次篩選,篩選的條件是是否有必要執(zhí)行 finalize()方法。當對象沒有覆蓋 finalize()方法或者已被虛擬機調(diào)用過,那么就認為是沒必要的。
  • 如果該對象有必要執(zhí)行 finalize()方法,那么這個對象將會放在一個稱為 F-Queue 的對隊列中,虛擬機會觸發(fā)一個 Finalize()線程去執(zhí)行,此線程是低優(yōu)先級的,并且虛擬機不會承諾一直等待它運行完,這是
  • 因為如果 finalize()執(zhí)行緩慢或者發(fā)生了死鎖,那么就會造成 F- Queue 隊列一直等待,造成了內(nèi)存回收系統(tǒng)的崩潰。GC 對處于 F-Queue 中的對象進行。

第二次被標記,這時,該對象將被移除”即將回收”集合,等待回收。

GC垃圾收集器

新生代收集器

1.Serial 垃圾收集器(單線程、復制算法)

串行收集器是最古老,最穩(wěn)定以及效率高的收集器,使用停止復制方法,只使用一個線程去串行回收;垃圾收集的過程中會Stop The World(服務暫停);參數(shù)控制:使用-XX:+UseSerialGC可以使用Serial+Serial Old模式運行進行內(nèi)存回收(這也是虛擬機在Client模式下運行的默認值) 

缺點:是串行效率較低。

2.ParNew 垃圾收集器(Serial+多線程)

ParNew收集器其實就是Serial收集器的多線程版本,使用停止復制方法。新生代并行,其它工作線程暫停。

參數(shù)控制:使用-XX:+UseParNewGC開關來控制使用ParNew+Serial Old收集器組合收集內(nèi)存;使用-XX:ParallelGCThreads來設置執(zhí)行內(nèi)存回收的線程數(shù)。

3.Parallel Scavenge 收集器(多線程復制算法、高效)JDK1.8 默認采用的新生代收集器。

ParallelScavenge收集器類似ParNew收集器,Parallel收集器更關注CPU吞吐量,即運行用戶代碼的時間/總時間,使用停止復制算法??梢酝ㄟ^參數(shù)來打開自適應調(diào)節(jié)策略,虛擬機會根據(jù)當前系統(tǒng)的運行情況收集性能監(jiān)控信息,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或最大的吞吐量;也可以通過參數(shù)控制GC的時間不大于多少毫秒或者比例。

參數(shù)控制:使用-XX:+UseParallelGC開關控制使用Parallel Scavenge+Serial Old收集器組合回收垃圾(這也是在Server模式下的默認值);使用-XX:GCTimeRatio來設置用戶執(zhí)行時間占總時間的比例,默認99,即1%的時間用來進行垃圾回收。使用-XX:MaxGCPauseMillis設置GC的最大停頓時間(這個參數(shù)只對Parallel Scavenge有效),用開關參數(shù)-XX:+UseAdaptiveSizePolicy可以進行動態(tài)控制,如自動調(diào)整Eden/Survivor比例,老年代對象年齡,新生代大小等,這個參數(shù)在ParNew下沒有。

老年代收集器

1.Serial Old收集器(單線程標記整理算法 )

老年代收集器,單線程收集器,串行,使用"標記-整理"算法(整理的方法是Sweep(清理)和Compact(壓縮),主要是運行在 Client 默認的 java 虛擬機默認的年老代垃圾收集器。

2.Parallel Scavenge 收集器

多線程機制與Parallel Scavenge差不錯,使用標記整理(與Serial Old不同,這里的整理是Summary(匯總)和Compact(壓縮),匯總的意思就是將幸存的對象復制到預先準備好的區(qū)域,而不是像Sweep(清理)那樣清理廢棄的對象)算法,在Parallel Old執(zhí)行時,仍然需要暫停其它線程。Parallel Old在多核計算中很有用。這個收集器是在JDK 1.6中,與Parallel Scavenge配合有很好的效果。

參數(shù)控制: 使用-XX:+UseParallelOldGC開關控制使用Parallel Scavenge +Parallel Old組合收集 器進行收集。

3.CMS 收集器(多線程標記清除算法)

Concurrent mark sweep(CMS)收集器是一種年老代垃圾收集器,其最主要目標是獲取最短垃圾回收停頓時間,和其他年老代使用標記-整理算法不同,它使用多線程的標記-清除算法。

整個過程分為6個步驟,其中初始標記、重新標記這兩個步驟仍然需要“Stop The World

  • 初始標記
  • 只是標記一下 GC Roots 能直接關聯(lián)的對象,速度很快,仍然需要暫停所有的工作線程。
  • 并發(fā)標記
  • 進行 GC Roots 跟蹤的過程,和用戶線程一起工作,不需要暫停工作線程。
  • 重新標記
  • 為了修正在并發(fā)標記期間,因用戶程序繼續(xù)運行而導致標記產(chǎn)生變動的那一部分對象的標記記錄,仍然
  • 需要暫停所有的工作線程。
  • 并發(fā)清除
  • 清除 GC Roots 不可達對象,和用戶線程一起工作,不需要暫停工作線程。由于耗時最長的并發(fā)標記和并發(fā)清除過程中,垃圾收集線程可以和用戶現(xiàn)在一起并發(fā)工作,所以總體上來看CMS 收集器的內(nèi)存回收和用戶線程是一起并發(fā)地執(zhí)行。

優(yōu)點:并發(fā)收集、低停頓

缺點:產(chǎn)生大量空間碎片、并發(fā)階段會降低吞吐量

4.G1收集器

Garbage first 垃圾收集器是目前垃圾收集器理論發(fā)展的最前沿成果,相比與 CMS 收集器,G1 收集器兩個最突出的改進是:

  • 基于標記-整理算法,不產(chǎn)生內(nèi)存碎片。
  • 可以非常精確控制停頓時間,在不犧牲吞吐量前提下,實現(xiàn)低停頓垃圾回收。

G1特點

  • G1通過將內(nèi)存空間分成區(qū)域(Region)的方式避免內(nèi)存碎片問題
  • Eden, Survivor, Old區(qū)不再固定、在內(nèi)存使用效率上來說更靈活
  • G1可以通過設置預期停頓時間(Pause Time)來控制垃圾收集時間避免應用雪崩現(xiàn)象
  • G1在回收內(nèi)存后會馬上同時做合并空閑內(nèi)存的工作、而CMS默認是在STW(stop the world)的時候做
  • G1會在Young GC中使用、而CMS只能在O區(qū)使用

G1 收集器避免全區(qū)域垃圾收集,它把堆內(nèi)存劃分為大小固定的幾個獨立區(qū)域,并且跟蹤這些區(qū)域的垃圾收集進度,同時在后臺維護一個優(yōu)先級列表,每次根據(jù)所允許的收集時間,優(yōu)先回收垃圾最多的區(qū)域。區(qū)域劃分和優(yōu)先級區(qū)域回收機制,確保 G1 收集器可以在有限時間獲得最高的垃圾收集效率。

GC垃圾收集器的選擇

JVM給了三種選擇:串行收集器、并行收集器、并發(fā)收集器。

但是串行收集器只適用于小數(shù)據(jù)量的情況,所以這里的選擇主要針對并行收集器和并發(fā)收集器。

吞吐量優(yōu)先的并行收集器

如上文所述,并行收集器主要以到達一定的吞吐量為目標,適用于科學技術和后臺處理等。Parallel Scavenge + ParallelOld

響應時間優(yōu)先的并發(fā)收集器

如上文所述,并發(fā)收集器主要是保證系統(tǒng)的響應時間,減少垃圾收集時的停頓時間。適用于應用服務器、電信領域ParNew + CMS

GC垃圾收集算法

標記-清除算法 (Mark Sweep)

算法分為2個階段:

  • 1.標記處需要回收的對象
  • 2.回收被標記的對象。

標記算法分為兩種:

1.引用計數(shù)算法(Reference Counting)

2.可達性分析算法(Reachability Analysis)。由于引用技術算法無法解決循環(huán)引用的問題,所以這里使用的標記算法均為可達性分析算法。 

缺點:產(chǎn)生了大量的非連續(xù)內(nèi)存,內(nèi)存碎片化嚴重,后續(xù)可能發(fā)生大對象不能找到可利用空間的問題。

復制算法 (Copying)

為了解決效率與內(nèi)存碎片問題,復制(Copying)算法出現(xiàn)了,它將內(nèi)存劃分為兩塊相等的大小,每次使用一塊,當這一塊用完了,就講還存活的對象復制到另外一塊內(nèi)存區(qū)域中,然后將當前內(nèi)存空間一次性清理掉。這樣的對整個半?yún)^(qū)進行回收,分配時按照順序從內(nèi)存頂端依次分配,這種實現(xiàn)簡單,運行高效。

不過這種算法將原有的內(nèi)存空間減少為實際的一半,代價比較高。 

缺點:可用內(nèi)存變?yōu)樵瓉淼囊话?,長期存活的對象復制頻率高

標記-整理算法(Mark-Compact)

標記階段和 Mark-Sweep 算法相同,標記后不是清理對象,而是將存活對象移向內(nèi)存的一端。然后清除端邊界外的對象

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java利用Geotools從DEM數(shù)據(jù)中讀取指定位置的高程信息全過程

    Java利用Geotools從DEM數(shù)據(jù)中讀取指定位置的高程信息全過程

    Geotools作為一款功能強大且開源的地理工具庫,為地理數(shù)據(jù)的處理和分析提供了豐富的類庫和便捷的接口,能夠很好地滿足從DEM數(shù)據(jù)中讀取高程信息這一實戰(zhàn)需求,本文將深入講解如何利用Geotools從獲取DEM數(shù)據(jù)到成功讀取指定位置高程信息的全過程,需要的朋友可以參考下
    2025-03-03
  • Java如何從json字符串中獲取某個值詳解

    Java如何從json字符串中獲取某個值詳解

    Java開發(fā)當中經(jīng)常需要Json格式的數(shù)據(jù),下面這篇文章主要給大家介紹了關于Java如何從json字符串中獲取某個值的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • Java 實現(xiàn)加密數(shù)據(jù)庫連接的步驟

    Java 實現(xiàn)加密數(shù)據(jù)庫連接的步驟

    這篇文章主要介紹了Java 實現(xiàn)加密數(shù)據(jù)庫連接的步驟,幫助大家更好的理解和使用Java處理數(shù)據(jù)庫,感興趣的朋友可以了解下
    2020-11-11
  • ?Java數(shù)據(jù)結構的十大排序

    ?Java數(shù)據(jù)結構的十大排序

    這篇文章主要介紹了?Java數(shù)據(jù)結構的十大排序,排序算法分為比較類排序和非比較類排序,具體的內(nèi)容,需要的朋友參考下面思維導圖及文章介紹,希望對你有所幫助
    2022-01-01
  • 手動部署java項目到k8s中的實現(xiàn)

    手動部署java項目到k8s中的實現(xiàn)

    本文主要介紹了手動部署java項目到k8s中的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Spring MVC Mybatis多數(shù)據(jù)源的使用實例解析

    Spring MVC Mybatis多數(shù)據(jù)源的使用實例解析

    項目需要從其他網(wǎng)站獲取數(shù)據(jù),因為是臨時加的需求,這篇文章主要介紹了Spring MVC Mybatis多數(shù)據(jù)源的使用實例解析,需要的朋友可以參考下
    2016-12-12
  • SpringBoot+Shiro+Redis+Mybatis-plus 實戰(zhàn)項目及問題小結

    SpringBoot+Shiro+Redis+Mybatis-plus 實戰(zhàn)項目及問題小結

    最近也是一直在保持學習課外拓展技術,所以想自己做一個簡單小項目,于是就有了這個快速上手 Shiro 和 Redis 的小項目,說白了就是拿來練手調(diào)調(diào) API,然后做完后拿來總結的小項目,感興趣的朋友一起看看吧
    2021-04-04
  • SpringBoot開發(fā)項目,引入JPA找不到findOne方法的解決

    SpringBoot開發(fā)項目,引入JPA找不到findOne方法的解決

    這篇文章主要介紹了SpringBoot開發(fā)項目,引入JPA找不到findOne方法的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中的LinkedHashSet源碼解讀

    Java中的LinkedHashSet源碼解讀

    這篇文章主要介紹了Java中的LinkedHashSet源碼解讀,LinkedHashSet?是?Java?中的一個集合類,它是?HashSet?的子類,并實現(xiàn)了?Set?接口,與?HashSet?不同的是,LinkedHashSet?保留了元素插入的順序,并且具有?HashSet?的快速查找特性,需要的朋友可以參考下
    2023-09-09
  • SpringBoot實現(xiàn)熱部署詳解

    SpringBoot實現(xiàn)熱部署詳解

    SpringBoot熱部署是一種開發(fā)時極為有用的功能,它能夠讓開發(fā)人員在代碼修改后無需手動重啟應用程序就能立即看到變化的效果,所以我本文就給打擊介紹一下為什么要使用熱部署以及實現(xiàn)熱部署的方式,需要的朋友可以參考下
    2023-07-07

最新評論