JVM調優參數大全及G1GC調優

一、JVM常見參數

1、標準參數

-verbose:class 打印每個class信息
-verbose:gc 打印每次gc信息

2、非標參數 -X

-Xloggc:filename 設置GC log文件的位置 -Xloggc:log/gc.log
-Xms大小 設置堆的初始化大小 -Xmx2048m =-XX:InitialHeapSize
-Xmx大小 設置堆的最大大小 -Xms1024m =-XX:MaxHeapSize 一般Xms=Xmx,防止擴容和縮容
-Xmn大小 設置年輕代大小(初始化和最大) -Xmn256m
-XX:NewSize -XX:MaxNewSize 分別指定年輕代的初始化和最大大小,建議年輕代佔堆大小的1/4 ~ 1/2
-Xss大小 設置線程棧大小 -Xss1m =-XX:ThreadStackSize

3、不穩定參數 -XX

-XX:ErrorFile=文件 設置錯誤日誌路徑 -XX:ErrorFile=./hs_err_pid%p.log %p爲當前進程號
-XX:OnError=命令 錯誤發生時執行命令 -XX:OnError="gcore %p;dbx - %p"
-XX:OnOutOfMemoryError=命令 內存溢出時執行命令
-XX:MaxDirectMemorySize=size 設置直接內存最大值 -XX:MaxDirectMemorySize=100m 默認爲0 當直接內存達到設置的最大值會FullGC
-XX:ObjectAlignmentInBytes=alignment 設置java對象的內存對齊,默認是8字節
-XX:ThreadStackSize 設置線程棧大小 -XX:ThreadStackSize=1m = -Xss
-XX:-UseBiasedLocking 禁用偏向鎖 默認開啓,不禁用 如果使用的是大量的沒有競爭的同步,使用偏向鎖會提升性能
-XX:-UseCompressedOops 禁用壓縮指針堆內存小於32G時默認開啓 開啓後,對象引用是32位而不是64位,可以提升性能。只有64位的jvm才生效
-XX:+DoEscapeAnalysis 開啓逃逸分析 默認開啓
-XX:+Inline 開啓方法內聯 默認開啓
-XX:InlineSmallCode=大小 設置應內聯的已編譯方法的最大代碼大小,只有小於此數值的纔會內聯 默認1000字節
-XX:MaxInlineSize=大小 設置要內聯方法的最大字節碼大小 默認35字節
-XX:+OptimizeStringConcat 開啓字符串連接優化 默認開啓
-XX:+PrintInlining 打印方法內聯 默認關閉,需和-XX:+UnlockDiagnosticVMOptions 一起使用
-XX:-TieredCompilation 關閉分層編譯 默認開啓
-XX:+HeapDumpOnOutOfMemoryError  OOM時堆內存dump到當前目錄
-XX:HeapDumpPath=路徑 設置堆內存dump的路徑 -XX:HeapDumpPath=/var/java_pid%p.hprof
-XX:+UnlockDiagnosticVMOptions 開啓jvm診斷功能選項

垃圾回收相關參數
-XX:+AggressiveHeap 開啓堆最優化設置 默認關閉
-XX:+CMSClassUnloadingEnabled 當使用CMS垃圾收集器時,允許類卸載 默認開啓
-XX:CMSExpAvgFactor=percent 指定垃圾收集消耗的時間百分比 默認這個數是25%,就是25
-XX:CMSInitiatingOccupancyFraction=percent 設置CMS回收開始的老年代百分比 默認-1,任何的負值表示會使用-XX:CMSTriggerRatio選項來定義這個百分比數
-XX:+CMSScavengeBeforeRemark 在CMS重新標記之前執行ygc操作  默認關閉 在remark時間過長時可以開啓;開啓減少remark的STW時間
-XX:CMSTriggerRatio=percent 設置CMS開始的百分比 默認80,((100 - MinHeapFreeRatio) + (double)( CMSTriggerRatio * MinHeapFreeRatio) / 100.0) / 100.0=92%
-XX:+UseCMSCompactAtFullCollection  在FULL GC的時候,對年老代的壓縮
-XX:CMSFullGCsBeforeCompaction=0  上面配置開啓的情況下,這裏設置多少次Full GC後,對年老代進行壓縮,
-XX:MinHeapFreeRatio=percent GC之後堆內存最小剩餘百分比,如果小於此值,則自動擴容 默認40%
-XX:MaxHeapFreeRatio=percent GC之後堆內存最大剩餘百分比,如果小於此值,則自動縮容 默認70%
-XX:ParallelGCThreads=threads 設置Parallel GC的線程數 默認根據cpu個數,<=8,則使用8個,>8個3+5N/81臺服務器只有1個jvm時使用默認值較好,如果有n個jvm,cpu個數 / n比較合適
-XX:ConcGCThreads=個數 併發GC的線程數 默認值取決於cpu個數 ConcGCThreads = (ParallelGCThreads + 3)/4
-XX:+DisableExplicitGC 使System.gc()顯式gc失效 默認不開啓,
-XX:G1HeapRegionSize=size 當使用G1收集器時,設置java堆被分割的region大小 1M~32M默認根據堆內存最優化設置
-XX:+G1PrintHeapRegions 打印G1收集器收集的區域  默認關閉
-XX:G1ReservePercent=percent  設置堆內存保留大小,以防晉升失敗 0~50 默認10%
-XX:InitialHeapSize=size 堆初始大小 =-Xms
-XX:MaxHeapSize=size 堆最大大小 =-Xmx
-XX:InitialSurvivorRatio=ratio 設置伊甸園區和倖存區初始比例 默認爲8:1
-XX:SurvivorRatio=ratio 設置伊甸園區和倖存區比例 默認爲8:1  8:1:1
XX:TargetSurvivorRatio YGC之後,倖存區期望百分比 默認 50%
XX:InitiatingHeapOccupancyPercent=percent 堆佔用達到多少開始併發垃圾回收 只有併發垃圾回收器生效
-XX:MaxGCPauseMillis=time GC最大暫停時間 ms 默認沒有最大暫停時間
-XX:MetaspaceSize=size 元空間多次擴容後超過此值就會full gc 默認大約20M 元空間使用本地內存。 儘量設置足夠,避免因爲這個區域內存不夠引發Full GC
-XX:MaxMetaspaceSize=size 設置元空間最大大小 默認不限制 建議和MetaspaceSize一樣大,一般256M
-XX:NewSize=size 設置年輕代初始大小 建議年輕代佔堆大小的1/4 ~ 1/2
-XX:MaxNewSize=size 設置年輕代最大大小 默認根據最大效能分配
-XX:MaxTenuringThreshold=threshold 最大晉升年齡,從年輕代到老年代 默認:15 - 並行回收器 6 - CMS
-XX:NewRatio=ratio 設置老年代和新生代比例 默認2 老年代 : (伊甸園 + 2個倖存區)
-XX:+PrintGC 打印GC信息 默認關閉
-XX:+PrintGCDetails 打印GC詳細信息 默認關閉
-XX:+PrintTenuringDistribution 打印晉升分配
-XX:+ScavengeBeforeFullGC Full gc之前先ygc 默認開啓
-XX:+UseTLAB 年輕代使用線程局部緩存 默認開啓  效率高
-XX:TLABSize=size 設置初始化thread-local allocation buffer (TLAB)大小
-XX:+UseAdaptiveSizePolicy  JDK 1.8 默認使用 UseParallelGC 垃圾回收器,該垃圾回收器默認啓動了 AdaptiveSizePolicy
-XX:+UseParallelGC 年輕代使用並行回收器
-XX:+UseParallelOldGC 老年代使用並行回收器
-XX:+UseParNewGC 爲配置CMS,年輕代使用ParNew回收器,CMS會默認開啓
-XX:+UseConcMarkSweepGC 使用CMS回收器
-XX:+UseG1GC 使用G1回收器
-XX:+UseGCOverheadLimit 限制GC的運行時間,通過統計GC時間來預測是否要OOM了,提前拋出異常,防止OOM發生 並行/併發回收器在GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC並且回收了不到2%的堆內存。用來避免內存過小造成應用不能正常工作
-XX:+UseStringDeduplication 開啓字符串去重 G1回收器生效
-XX:AutoBoxCacheMax=20000 加大Integer Cache
-XX:+PrintPromotionFailure 知道是多大的新生代對象晉升到老生代失敗從而引發Full GC時的。

二、G1GC

G1GC

G1 GC是啓發式算法,會動態調整年輕代的空間大小。目標也就是爲了達到接近預期的暫停時間。
G1提供了兩種GC模式,Young GC和Mixed GC,兩種都是Stop The World(STW)的。

Young GC

Young GC主要是對Eden區進行GC,它在Eden空間耗盡時會被觸發。在這種情況下,Eden空間的數據移動到Survivor空間中,如果Survivor空間不夠,Eden空間的部分數據會直接晉升到年老代空間。Survivor區的數據移動到新的Survivor區中,也有部分數據晉升到老年代空間中。最終Eden空間的數據爲空,GC停止工作,應用線程繼續執行。

Mixed GC

Mix GC不僅進行正常的新生代垃圾收集,同時也回收部分後臺掃描線程標記的老年代分區。
它的GC步驟分2步: 全局併發標記(global concurrent marking) 拷貝存活對象(evacuation)
在進行Mix GC之前,會先進行global concurrent marking(全局併發標記)。 global concurrent marking的執行過程是怎樣的呢?
在G1 GC中,它主要是爲Mixed GC提供標記服務的,並不是一次GC過程的一個必須環節。
global concurrent marking的執行過程分爲五個步驟:

  • 初始標記(initial mark,STW)在此階段,G1 GC 對根對象進行標記。該階段與常規的 (STW) 年輕代垃圾回收密切相關。
  • 根區域掃描(root region scan)G1 GC 在初始標記的存活區掃描對老年代的引用,並標記被引用的對象。該階段與應用程序(非 STW)同時運行,並且只有完成該階段後,才能開始下一次 STW 年輕代垃圾回收。
  • 併發標記(Concurrent Marking)G1 GC 在整個堆中查找可訪問的(存活的)對象。該階段與應用程序同時運行,可以被 STW 年輕代垃圾回收中斷
  • 最終標記(Remark,STW)該階段是 STW 回收,幫助完成標記週期。G1 GC 清空 SATB 緩衝區,跟蹤未被訪問的存活對象,並執行引用處理。
  • 清除垃圾(Cleanup,STW)在這個最後階段,G1 GC 執行統計和 RSet 淨化的 STW 操作。在統計期間,G1 GC 會識別完全空閒的區域和可供進行混合垃圾回收的區域。清理階段在將空白區域重置並返回到空閒列表時爲部分併發。

Young GC:選定所有新生代裏的region。通過控制新生代的region個數來控制young GC的開銷。
Mixed GC:選定所有新生代裏的region,外加根據global concurrent marking統計得出收集收益高的若干老年代region。在用戶指定的開銷目標範圍內儘可能選擇收益高的老年代region。

在G1中,有一種特殊的區域,叫Humongous區域。 如果一個對象佔用的空間超過了分區容量50%以上,G1收集器就認爲這是一個巨型對象。這些巨型對象,默認直接會被分配在年老代。


三、G1調優手冊

暫停時間:用-XX:MaxGCPauseMillis來指定,默認值200ms。這是一個軟性目標,G1會盡量達成,如果達不成,會逐漸做自我調整。對於Young GC來說,會逐漸減少Eden區個數,減少Eden空間那麼Young GC的處理時間就會相應減少;對於Mixed GC,G1會調整每次Choose Cset的比例,默認最大值是10%,當然每次選擇的Cset少了,所要經歷的Mixed GC的次數會相應增加。同時減少Eden的總空間時,就會更加頻繁的觸發Young GC,也就是會加快Mixed GC的執行頻率,因爲Mixed GC是由Young GC觸發的,或者說藉機同時執行的。頻繁GC會對對應用的吞吐量造成影響,每次Mixed GC回收時間太短,回收的垃圾量太少,可能最後GC的垃圾清理速度趕不上應用產生的速度,那麼可能會造成串行的Full GC,這是要極力避免的。所以暫停時間肯定不是設置的越小越好,當然也不能設置的偏大,轉而指望G1自己會盡快的處理,這樣可能會導致一次全部併發標記後觸發的Mixed GC次數變少,但每次的時間變長,STW時間變長,對應用的影響更加明顯。
Region大小:用-XX:G1HeapRegionSize來指定,若未指定則默認最多生成2048塊,每塊的大小需要爲2的冪次方,如1,2,4,8,16,32,最大值爲32M。Region的大小主要是關係到Humongous Object的判定,當一個對象超過Region大小的一半時,則爲巨型對象,那麼其會至少獨佔一個Region,如果一個放不下,會佔用連續的多個Region。當一個Humongous Region放入了一個巨型對象,可能還有不少剩餘空間,但是不能用於存放其他對象,這些空間就浪費了。所以如果應用裏有很多大小差不多的巨型對象,可以適當調整Region的大小,儘量讓他們以普通對象的形式分配,合理利用Region空間。
新生代比例:一般不需要設置新生代大小。讓G1自己根據最大停頓時間動態調整。新生代比例有兩個數值指定,下限:
-XX:G1NewSizePercent,默認值5%,上限:-XX:G1MaxNewSizePercent,默認值60%。G1會根據實際的GC情況(主要是暫停時間)來動態的調整新生代的大小,主要是Eden Region的個數。最好是Eden的空間大一點,畢竟Young GC的頻率更大,大的Eden空間能夠降低Young GC的發生次數。但是Mixed GC是伴隨着Young GC一起的,如果暫停時間短,那麼需要更加頻繁的Young GC,同時也需要平衡好Mixed GC中新生代和老年代的Region,因爲新生代的所有Region都會被回收,如果Eden很大,那麼留給老年代回收空間就不多了,最後可能會導致Full GC。
併發GC線程數:通過 -XX:ConcGCThreads來指定,默認是-XX:ParallelGCThreads/4,也就是在非STW期間的GC工作線程數,當然其他的線程很多工作在應用上。當併發週期時間過長時,可以嘗試調大GC工作線程數,但是這也意味着此期間應用所佔的線程數減少,會對吞吐量有一定影響。
並行GC線程數:通過 -XX:ParallelGCThreads來指定,也就是在STW階段工作的GC線程數,其值遵循以下原則:
① 如果用戶顯示指定了ParallelGCThreads,則使用用戶指定的值。
② 否則,需要根據實際的CPU所能夠支持的線程數來計算ParallelGCThreads的值,計算方法見步驟③和步驟④。
③ 如果物理CPU所能夠支持線程數小於8,則ParallelGCThreads的值爲CPU所支持的線程數。這裏的閥值爲8,是因爲JVM中調用nof_parallel_worker_threads接口所傳入的switch_pt的值均爲8。
④ 如果物理CPU所能夠支持線程數大於8,則ParallelGCThreads的值爲8加上一個調整值,調整值的計算方式爲:物理CPU所支持的線程數減去8所得值的5/8或者5/16,JVM會根據實際的情況來選擇具體是乘以5/8還是5/16。
比如,在64線程的x86 CPU上,如果用戶未指定ParallelGCThreads的值,則默認的計算方式爲:ParallelGCThreads = 8 + (64 - 8) * (5/8) = 8 + 35 = 43。
被納入Cset的Region的存活空間佔比閾值:通過 -XX:G1MixedGCLiveThresholdPercent指定,不同版本默認值不同,有65%和85%。在全局併發標記階段,如果一個Region的存活對象的空間佔比低於此值,則會被納入Cset。此值直接影響到Mixed GC選擇回收的區域,當發現GC時間較長時,可以嘗試調低此閾值,儘量優先選擇回收垃圾佔比高的Region,但此舉也可能導致垃圾回收的不夠徹底,最終觸發Full GC。
觸發全局併發標記的老年代使用佔比:通過-XX:InitiatingHeapOccupancyPercent指定,默認值45%,也就是老年代佔堆的比例超過45%。如果Mixed GC週期結束後老年代使用率還是超過45%,那麼會再次觸發全局併發標記過程,這樣就會導致頻繁的老年代GC,影響應用吞吐量。同時老年代空間不大,Mixed GC回收的空間肯定是偏少的。可以適當調高IHOP的值,當然如果此值太高,很容易導致年輕代晉升失敗而出發Full GC,所以需要多次調整測試。
觸發Mixed GC的堆垃圾佔比:通過-XX:G1HeapWastePercent指定,默認值5%,也就是在全局標記結束後能夠統計出所有Cset內可被回收的垃圾佔整對的比例值,如果超過5%,那麼就會觸發之後的多輪Mixed GC,如果不超過,那麼會在之後的某次Young GC中重新執行全局併發標記。可以嘗試適當的調高此閾值,能夠適當的降低Mixed GC的頻率。
每輪Mixed GC回收的Region最大比例:通過-XX:G1OldCSetRegionThresholdPercent指定,默認10%,也就是每輪Mixed GC附加的Cset的Region不超過全部Region的10%,最多10%,如果暫停時間短,那麼可能會少於10%。一般這個值不需要額外調整。
一個週期內觸發Mixed GC最大次數:通過-XX:G1MixedGCCountTarget指定,默認值8。也就是在一次全局併發標記後,最多接着8此Mixed GC,也就是會把全局併發標記階段生成的Cset裏的Region拆分爲最多8部分,然後在每輪Mixed GC裏收集一部分。這個值要和上一個參數配合使用,8*10%=80%,應該來說會大於每次標記階段的Cset集合了。一般此參數也不需額外調整。
G1爲分配擔保預留的空間比例:通過-XX:G1ReservePercent指定,默認10%。也就是老年代會預留10%的空間來給新生代的對象晉升,如果經常發生新生代晉升失敗而導致Full GC,那麼可以適當調高此閾值。但是調高此值同時也意味着降低了老年代的實際可用空間。
謹慎使用Soft Reference:如果SoftReference過多,會有頻繁的老年代收集。-XX:SoftRefLRUPolicyMSPerMB參數,可以指定每兆堆空閒空間的軟引用的存活時間,默認值是1000,也就是1秒。可以調低這個參數來觸發更早的回收軟引用。如果調高的話會有更多的存活數據,可能在GC後堆佔用空間比會增加。 對於軟引用,還是建議儘量少用,會增加存活數據量,增加GC的處理時間。
晉升年齡閾值:通過-XX:MaxTenuringThreshold指定,默認值15。一般新生對象經過15次Young GC會晉升到老年代,巨型對象會直接分配在老年代,同時在Young GC時,如果相同age的對象佔Survivors空間的比例超過 -XX:TargetSurvivorRatio的值(默認50%),則會自動將此次晉升年齡閾值設置爲此age的值,所有年齡超過此值的對象都會被晉升到老年代,此舉可能會導致老年代需要不少空間應對此種晉升。一般這個值不需要額外調整。


四、G1參數樣例

8核 8G內存,使用G1GC

-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1HeapRegionSize=4M
-XX:MaxTenuringThreshold=12
-XX:InitiatingHeapOccupancyPercent=40
-XX:ConcGCThreads=4 當前核心數的一半
-XX:+UseStringDeduplication
-XX:AutoBoxCacheMax=20000
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
-XX:+PrintPromotionFailure
-XX:+HeapDumpOnOutOfMemoryErro
-XX:HeapDumpPath=${LOGDIR}/java_pid${pid}.hprof
-Xloggc:/data/log/gc-myapp.log 
-verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails
-XX:+DisableExplicitGC 

在這裏插入圖片描述


  • 我的公衆號:Coding摳腚
  • 人生海海,山山而川。
    Coding摳腚
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章