日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java_opts gc回收器_JVM之垃圾回收机制(GC)

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java_opts gc回收器_JVM之垃圾回收机制(GC) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JVM之垃圾回收機制全解(GC)文章底部有思維導圖,較為清晰,可參考

導讀:垃圾回收是Java體系中最重要的組成部分之一,其提供了一套全自動的內存管理方案,要想掌握這套管理方案,就必須了解垃圾回收器的工作原理。本文介紹了垃圾回收的概念,算法,垃圾回收器及我在工作中遇到的一些關于GC的優化實例。

先來簡單了解下JVM:

-------------------------------------------------------------

一、heap內存劃分

-------------------------------------------------------------

1.年輕代:分三個區。一個Eden區,兩個Survivor區(from Survivor(s0)區和to Survivor(s1)區)。

大部分對象在Eden區中生成。當Eden區滿時,還存活的對象將被復制到Survivor區(兩個中的一個),當這個Survivor區滿時,此區的存活對象將被復制到另外一個Survivor區,當這個Survivor去也滿了的時候,從第一個Survivor區復制過來的并且此時還存活的對象,將被復制“年老區(Tenured)”。

2.年老代

在年輕代中經歷了N次((ParNew默認15))垃圾回收后仍然存活的對象,就會被放到年老代中。年輕代放不下的大對象直接進入老年代。

tip1:對象動態年齡計算規則

虛擬機并不是永遠地要求對象的年齡必須達到了MaxTenuringThreshold(默認15次)才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。

3.持久代

用于存放靜態文件,如今Java類、方法等

JDK1.8中,永久代已經從java堆中移除,String直接存放在堆中,類的元數據存儲在meta space中,meta space占用外部內存,不占用堆內存。

-------------------------------------------------------------

二、GC回收算法

-------------------------------------------------------------

2.1 標記清除算法:標記清除分為兩個階段,標記階段(標記從根節點開始的所有可達對象,未標記即未被引用)和清除階段。缺點:兩個階段效率都很低;回收后內存空間不連續,產生碎片多,易導致提前GC。

2.2 復制算法:內存等分兩塊,相互復制存活的對象后清洗垃圾 缺點:內存利用率低

2.3 標記壓縮法:先標記,然后存活的向一段移動,清理存活端標記以外的內存。(老年代使用,無需需要第二塊相同的內存) 優缺點:無內存碎片,但是耗時。

2.4 分代算法:復制算法(新生代使用) ,標記壓縮法和標記清除法(老年代使用)。卡表(數據結構,一個比特位的集合),用來表示老年代對象是否持有新生代對象的引用,新生代無需再花時間確認對象是否被持有,可以加快新生代回收的速度。

2.5 分區算法:將整個堆空間劃分為連續不同的小的空間,獨立管理,獨立回收。

垃圾回收基本思想在于如何判斷對象的可觸及性。根據標記清除算法,可以掃描出root節點未觸及持有的對象,但一個無法觸及持有的對象有可能在某個時間下使自己復活。

對象的可觸及性的三種狀態:

可觸及的

可復活的(finalize()函數)

不可觸及的(finalize()函數只能調用一次)

2.6 引用和可觸及的強度分為4個級別

強引用:任何時候都不會被系統回收,亦可能會引起OOM。 例:StringBuffer str = new StringBuffer("juejin");

軟引用:GC不一定回收,但堆空間不足時會被回收。OOM之前一定會回收,所以軟引用不會引起OOM。 使用SoftReference創建的對象。

弱引用:發現即回收。使用WeakReference創建的對象。使用PhantomReference創建的對象。

虛引用:隨時可回收。

-------------------------------------------------------------

三、分代垃圾回收

-------------------------------------------------------------

3.1 young代采用復制算法

3.2 old代使用標記清除或者標記清理

3.3 Tip:對象優先在Eden去分配,大的對象直接進入老年代,長期存活對象進入老年代。

-------------------------------------------------------------

四、垃圾回收器

-------------------------------------------------------------

tip:Stop The World(STW)1、為了讓垃圾回收器可以正常切高效執行。2、保證了系統某個瞬間的一致性。3、有益于垃圾回收器更好地標記垃圾對象。

4.1 串行回收器

單線程GC,啟動時會停止應用,適用于配置小的服務器(1C2G),基本已棄用

4.2 并行回收器PS(吞吐量優先)

JDK1.6~1.8默認使用。垃圾線程并行,啟動時應用會等待。

PS的新生代回收器有兩個。

(1)、ParNew回收器:多線程執行垃圾回收。PS的線程數量可以用-XX:ParallelGCThreads指定。當CPU<8時,ParallelGCThreads的值=CPU,CPU>8時,ParallelGCThreads的值=3+((5*CPU_count)/8)。適用于交互較弱的場景。JDK1.8以上已經被刪除。

(2)、Parallel回收器:與ParNew一樣是多線程獨占式。但其特點是關注系統的吞吐量(吞吐量:花費在垃圾收集時間和花費在應用時間的占比)。

使用方法:-XX:+UseParallelGC(設置老年代-XX:+UseParallelOidGC)

4.3 并發回收器(響應時間優先)(并行GC前會額外觸發新生代的GC)

與并行回收器不相同的是,并發收集器是非獨占式,在進行垃圾回收的時候應用程序也可以運行。

主要有Concurrent Mask Sweep(CMS)和G1

JDK1.9默認使用G1。適用于對響應時間有要求的場景。響應時間:花費在應用時間和花費在垃圾收集時間的占比。

CMS(以獲取最短回收停頓時間為目標的收集器,基于并發“標記清理”實現)

過程:1)初始標記(標記root對象) 2)并發標記 3)預清理(準備及控制停頓時間) 4)重新標記 5)并發清除 6)并發重置

優點:并發收集、低停頓。

缺點:

1)CMS對CPU資源敏感。在并發階段,它雖然不會導致用戶線程停頓,但是會因為占用了一部分線程而導致應用程序變慢,總吞吐量會降低。

2)CMS無法處理浮動垃圾,可能會出現“Concurrent Mode Failure(并發模式故障)”失敗而導致Full GC產生。

3)CMS容易出現大量空間碎片。當空間碎片過多,將會給大對象分配帶來很大的麻煩,往往會出現老年代還有很大空間剩余,但是無法找到足夠大的連續空間來分配當前對象,不得不提前觸發一次Full GC。

4)老年代垃圾回收過程中,如果出現資源不夠用,則會強制進行老年代串行回收,應用暫停時間更長,影響更大。

G1(面向服務端應用的垃圾收集器)

1.7正式使用,且使用了全新的算法,看起來有取代CMS的趨勢。

保留了分代的概念,但是從堆結構上看,分代內存并不是連續的。如圖:

在并行性和并發性的基礎上,可以同時兼顧年輕代和年老代,還可以進行空間整理,每次GC之后會自動進行碎片整理,減少碎片空間。最后還有可預見性,G1可以選取部分區域進行內存回收。

過程:1)初始標記(標記root對象)(eden區會被清空) 2)根區域掃描 3)并發標記 4)重新標記 5)獨占清理 (計算各個區域存活對象和GC回收比例)6)并發清理

混合回收:在年輕代滿時,觸發年輕代收集;隨著老年代內存增長,當到達IHOP閾值-XX:InitiatingHeapOccupancyPercent(老年代占整堆比,默認45%)時,G1開始準備收集老年代空間。首先經歷并發標記周期,識別出垃圾占比較高的老年代分區。但隨后G1并不會馬上開始一次混合收集,而是讓應用線程先運行一段時間,等待觸發一次年輕代收集。在這次STW中,G1將保準整理混合收集周期。接著再次讓應用線程運行,當接下來的幾次年輕代收集時,將會有老年代分區加入到CSet中,即觸發混合收集,這些連續多次的混合收集稱為混合收集周期(Mixed Collection Cycle)

特點:

1、并行于并發:G1能充分利用CPU多核,使用多個CPU來縮短stop-The-World停頓時間。

2、分代收集:雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但是還是保留了分代的概念。

3、空間整合:與CMS的“標記--清理”算法不同,G1從整體來看是基于“標記整理”算法實現的收集器;從局部上來看是基于“復制”算法實現的。

4、可預測的停頓:這是G1相對于CMS的另一個大優勢,降低停頓時間是G1和CMS共同的關注點,但G1除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內。

-------------------------------------------------------------

五、調優思路

-------------------------------------------------------------

5.1 前瞻

1、嘗試多種垃圾回收器,G1并不是最好的

2、并發不等于并行。垃圾回收的過程實際上有兩步,啟動GC周期和GC自身運行,這是不同的兩件事。并發針對的是GC周期,而并行針對GC算法自身。

3、平均事務時間不是最需要被關注的指標,有可能用戶正好經歷了那個長時間GC的場景,那將是毀滅性的。

4、GC調優并不能解決所有的事。如果程序修改程度大,那應該優先優化架構及代碼。

5、GC日志并不會對性能造成太大的影響,在GC未被優化之前,開啟GC日志是有必要的。

6、降低新對象的分配率可以改善GC的運行狀況。粗略地把系統中的對象分為三種:長命(long-lived)對象,對它們我們一般做不了什么;中等壽命(mid-lived)對象,最大的問題可能出現在這;短命(short-lived)對象,它們的釋放和回收通常都很快,在下個GC周期來臨時就會消失

5.2 思路

1、理解應用需求和問題。

2、掌握GC的狀態。

3、思考選擇的GC是否符合我們的應用特征。

4、分析確認需要調整的參數。

5、驗證調優。

5.3 查看設置參數

java -XX:+PrintFlagsInitial 查看初始值

-XX:+PrintFlagsFinal 查看最終值(初始值可能被修改掉)

-Xms 默認情況下堆內存的64分之一

-Xmx 默認情況下對內存的4分之一

-Xmn 默認情況下堆內存的3分之一

-XX:NewRatio 默認為2

-XX:SurvivorRatio 默認為8

-XX:+PrintGCDetails 開啟GC詳細日志-Xloggc:/cpic/cpicapp/perfma/xowl/../logs/xowl/gc.log -XX:+PrintGCDetails

5.4 GC一般合理表現

分析結果顯示GC耗時在0.1-0.3秒以內的話,一般不需要花費額外的時間做GC調優。然而, 如果GC耗時達到1-3秒甚至10秒以上,就需要立即對系統進行GC調優 。

Minor GC執行迅速(50毫秒以內)

Minor GC執行不頻繁(間隔10秒左右一次)

Full GC執行迅速(1秒以內)

Full GC執行不頻繁(間隔10分鐘左右一次)

-------------------------------------------------------------

六、參數調優

-------------------------------------------------------------

6.1 PS

6.1.1 吞吐量:-XX:GCTimeRatio=垃圾收集時間與應用程序時間的比率設置為1/(1+),默認值是99%(垃圾收集時間的1%)。

-Xmx:指定最大堆占用空間。

優先級保證:暫停時間>吞吐量>堆空間。如果不設置初始堆內存和最大堆內存,則初始堆大小為物理內存的1/64,最大內存為1/4,年輕代大小為堆內存的1/3。

-Xms (初始堆內存) and -Xmx (最大堆內存):

如果知道應用程序需要多少堆才能正常工作,那么可以將-Xms和-Xmx設置為相同的值。如果不知道,那么JVM將首先使用初始堆大小,然后自動增長,直到它找到堆使用和性能之間的平衡。

三個重要參數:1、-XX:MaxGCPauseTimeMillis:設置最大垃圾回收時間停頓時間。

2、-XX:GCTimeRatio:設置吞吐量大小。

3、-XX:UseAdaptiveSizePolicy:自適應模式。新生代大小,eden區與survivor區的比例,晉升老年代的對象年齡等參數會被自動調整。

CMS

使用方法:-XX:+UseConcMarkSweepGC

并發線程數:(ParallelGCThreads+3)/4。也可用通過-XX:ConcGCThreads或者-XX:ParallelCMSThreads手工設置。

因為并發性質,所以CMS不會等到堆飽和時才進行垃圾回收。默認值為老年代占用率68%,通過-XX:CMSInitiatingOccupancyFraction設置。

內存壓縮:設定多少次之后GC回收之后對內存進行一次壓縮。-XX:CMSFullGCsBeforeCompaction。默認0

開啟-XX:CMSClassUnloadingEnable,可以在需要時候Perm區的還會觸發一次FullGC。

6.2 G1

6.2.1 啟用G1(常用):-XX:+UseG1GC

堆內存(常用):-XX:InitialHeapSize(初始堆內存)-XX:MaxHeapSize(最大堆內存)

年輕代設置(常用):-XX:NewSize(最小) -XX:MaxNewSize(最大)

暫停時間(常用):-XX:MaxGCPauseTimeMillis=(默認200ms)

空閑堆占比:-XX:MinHeapFreeRatio=40(GC后,如果發現空閑堆內存占到整個預估堆內存的40%,則放大堆內存的預估最大值,但不超過固定最大值。)-XX:MaxHeapFreeRatio=70

最大暫停間隔時間:-XX:PauseTimeIntervalMillis

GC停頓時候的并行的GC收集線程數:-XX:ParallelGCThreads=< ergo>根據虛擬機所在的主機的可用CPU線程數來計算的:如果CPU少于8個這個值就是cpu的數量,否則,就等于cpu數量*5/8。每個停頓開始的時候,最大的GC線程數還受限于最大的堆內存,G1的內個線程能使用的最大堆內存是由-XX:HeapSizePerGCThread來設置的。

與應用并發執行的GC線程數:-XX:ConcGCThreads=< ergo>:默認是-XX:ParallelGCThreads/4

region的大小:-XX:G1HeapRegionSize=< ergo>整個堆大概有2048個region,region的大小可以在1-32M之間,必須是2的次方。調整之后會影響分配對象的大小及停頓時間。

可分配的最大對象的大小: -XX:G1HeapRegionSize-XX:G1MaxNewSizePercent

-------------------------------------------------------------

七、針對項目經驗集

-------------------------------------------------------------

7.1 這幾種GC收集器相比之下,只要JDK版本在1.7u4及以上,推薦使用G1收集器。JDK1.7,1.8都默認使用PS(并行收集器)

7.2 尤其注意容器項目,容器設置的JVM配置內存大小不能大于容器內存大小,否則參數配置無效。

7.3 調優實例

7.3.1 實例一(集團2018版XXXXXXXX系統):

壓測表現:穩定性壓測時結果不穩定且內存消耗一直80%左右,影響時間3天。

內存分析表現:堆內存很大(7G)但年輕代內存非常小,年輕代minGC頻繁,老年代內存一直增加直至觸發majorGC,且GC暫停時間長,平均200~300ms

調優:調整年輕代內存為3G

export JAVA_OPTS="$JAVA_OPTS -Xmx7g -Xms7g -XX:NewSize=3g -XX:MaxNewSize=3g -XX:+UseG1GC"

優化結果:

復壓,內存穩定在60%左右,年輕代GC頻繁度減小,GC耗時100ms左右,老年代穩定無majorGC

7.3.2 實例二(壽險2013版XXXXXXXX系統):

壓測表現:壓測時壓不上去,服務器消耗未滿載。且壓的時間長了TPS會有斷崖式下降,TPS和相應時間非常不穩定。影響時間2天。

內存分析表現:heap內存只設置了2G,容器是3.5C7G,老年代一直增長直至觸發majorGC,GC頻繁且GC暫停時間不穩定。

調優:調整heap內存大小7G,新生代3G。

JAVA_OPTS="-Xmx7000m -Xms7000m -Xmn3072m -XX:PermSize=256M -XX:MaxPermSize=256M

調優結果:

TPS增長40~50且穩定。老年代穩定無majorGC。minorGC頻繁度減小,GC暫停時間降低且穩定在幾十ms以內。

7.3.3 Tip1:年輕代內存并不是越大越好,雖然會減小GC的頻率,但是在GC時會增加回收時間造成GC暫停時間長。

Tip2:docker系統,如果容器內存4G,堆內存設置6G,進程可以啟動且顯示為6G,但實際只能使用到4G。

Tip3:如果開發和測試都不清楚如何設置堆大小及年輕代大小,可以參考perfma產品 http://xxfox.perfma.com/ ,填寫相關參數會給出調優建議

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的java_opts gc回收器_JVM之垃圾回收机制(GC)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。