JVM——參數說明


 

前言

本文對常用 JVM 常用參數做了一個整理,但是參數的使用很復雜,本文僅僅提供常用參數的查閱,具體的使用還是需要根據具體的情況。

JVM 是一個開放的標准,誰可以來實現 JVM,這導致不同 JVM 實現的參數有所不同,本文基於 Hotspot 虛擬機。

JVM 參數很多,總體上可以分成三類:

  • -標准參數,比如 -verbose:gc 這類表示標准實現,所有的虛擬機都需要實現這些參數的功能,且向后兼容;

  • -X非標准參數,默認 JVM 會實現這些參數的功能,但是不保證所有的 JVM 實現都滿足,且不保證向后兼容;

  • -XX非 Stable 參數,這些參數在不同的 JVM 上會有不同的實現,這些參數不推薦在生成環境中使用,以后很有可能會被取消,需要慎重使用;

關於JVM選項的幾點:

  • 布爾型參數:-XX:+ 表示打開, -XX:- 表示關閉。(比如-XX:+PrintGCDetails);
  • 數字型參數:通過 -XX:= 設定。數字可以是m/M(兆字節),k/K(千字節),g/G(G字節)。比如:32K表示32768字節;
  • 字符行參數:通過 -XX:= 設定,通常用來指定一個文件,路徑,或者一個命令列表。(比如-XX:HeapDumpPath=./java_pid.hprof)

關於JVM參數查看:

  • java -help:該命令可以列出 java 應用啟動時標准選項(不同的JVM實現是不同的);
  • java -X:該命令可以列出不標准的參數(這是JVM的擴展特性)。
  • 任何一個JVM參數的默認值可以通過 java -XX:+PrintFlagsFinal -version |grep JVMParamName獲取,例如: java -XX:+PrintFlagsFinal -version |grep MetaspaceSize

 

標准參數

標准參數,所有的虛擬機都需要實現這些參數的功能,且向后兼容。可通過 java -help 命令來檢索。

常用的參數說明:

  • -server:設置jvm使server模式,特點是啟動速度比較慢,但運行時性能和內存管理效率很高,適用於生產環境。在具有64位能力的jdk環境下將默認啟用該模式,而忽略-client參數。
  • -javaagent:指定jvm啟動時裝入java語言設備代理。
  • -verbose:
    • -verbose:class:輸出jvm載入類的相關信息,當jvm報告說找不到類或者類沖突時可此進行診斷。
    • -verbose:gc:輸出每次GC的相關情況,當GC日志被保存為文件時,這個參數無效。
    • -verbose:jni:輸出native方法調用的相關情況,一般用於診斷jni調用錯誤信息。

 

非標准參數

非標准參數又稱為擴展參數,非標准化的參數在將來的版本中可能會改變。所有的這類參數都以-X開始,並且可以用 java -X 來檢索。

注意,不能保證所有參數都可以被檢索出來,其中就沒有-Xcomp。例如: 

常用的參數說明:

  • -Xms:設置JVM最小內存(比如:-Xms512m)。此值可以設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。
  • -Xmx:設置JVM最大可用內存(比如:-Xmx512m)。
  • -Xmn:設置年輕代的內存(比如:-Xmn200m)。此處的大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是(eden+1 survivor space)不同的。
  • -Xss:設置每個線程的堆棧大小(比如:-Xss128k)。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。根據應用的線程所需內存大小進行調整。在相同物理內存下,減小這個值能生成更多的線程。
  • -Xloggc:file:與-verbose:gc功能類似,只是將每次GC事件的相關情況記錄到一個文件中,文件的位置最好在本地,以避免網絡的潛在問題。若與verbose命令同時出現在命令行中,則以-Xloggc為准。
  • -Xnoclassgc:表示關閉對類的垃圾回收。因為其阻止內存回收,所以可能會導致OutOfMemoryError錯誤,請謹慎使用。

 

非 Stable 參數

非Stable參數列表(以-XX作為前綴)在jvm中可能是不健壯的,SUN也不推薦使用,后續可能會在沒有通知的情況下就直接取消了;

但是由於這些參數中的確有很多是對我們很有用的,比如我們經常會見到的-XX:PermSize、-XX:MaxPermSize等等;

下面我們將就Java HotSpot VM中 -XX: 的可配置參數列表進行描述,這些參數可以被松散的聚合成三類:

  • 行為參數(Behavioral Options):用於改變jvm的一些基礎行為;
  • 性能調優(Performance Tuning):用於jvm的性能調優;
  • 調試參數(Debugging Options):一般用於打開跟蹤、打印、輸出等jvm參數,用於顯示jvm更加詳細的信息;

由於sun官方文檔中對各參數的描述也都非常少(大多只有一句話),而且大多涉及OS層面的東西,很難描述清楚,所以以下是挑選了一些我們開發中可能會用得比較多的配置項,

若需要查看所有參數列表,可以點擊HotSpot VM Specific Options.查看原文;

行為參數

參數及其默認值 描述
-XX:-DisableExplicitGC 禁止調用System.gc();但jvm的gc仍然有效
-XX:+MaxFDLimit 最大化文件描述符的數量限制
-XX:+ScavengeBeforeFullGC 新生代GC優先於Full GC執行
-XX:+UseGCOverheadLimit 在拋出OOM之前限制jvm耗費在GC上的時間比例
-XX:-UseConcMarkSweepGC 對老生代采用並發標記交換算法進行GC
-XX:-UseParallelGC 啟用並行GC
-XX:-UseParallelOldGC 對Full GC啟用並行,當-XX:-UseParallelGC啟用時該項自動啟用
-XX:-UseSerialGC 啟用串行GC
-XX:+UseThreadPriorities 啟用本地線程優先級
上面表格中黑體的三個參數代表着jvm中GC執行的三種方式,即 串行、並行、並發
  • 串行(SerialGC):是jvm的默認GC方式,一般適用於小型應用和單處理器,算法比較簡單,GC效率也較高,但可能會給應用帶來停頓;
  • 並行(ParallelGC):是指GC運行時,對應用程序運行沒有影響,GC和app兩者的線程在並發執行,這樣可以最大限度不影響app的運行;
  • 並發(ConcMarkSweepGC):是指多個線程並發執行GC,一般適用於多處理器系統中,可以提高GC的效率,但算法復雜,系統消耗較大;

性能調優參數

參數及其默認值 描述
-XX:LargePageSizeInBytes=4m 設置用於Java堆的大頁面尺寸
-XX:MaxHeapFreeRatio=70 GC后java堆中空閑量占的最大比例
-XX:MaxNewSize=size 新生成對象能占用內存的最大值
-XX:MaxPermSize=64m 老生代對象能占用內存的最大值
-XX:MinHeapFreeRatio=40 GC后java堆中空閑量占的最小比例
-XX:NewRatio=2 新生代內存容量與老生代內存容量的比例
-XX:NewSize=2.125m 新生代對象生成時占用內存的默認值
-XX:ReservedCodeCacheSize=32m 保留代碼占用的內存容量
-XX:ThreadStackSize=512 設置線程棧大小,若為0則使用系統默認值
-XX:+UseLargePages 使用大頁面內存

 我們在日常性能調優中基本上都會用到以上黑體的這幾個屬性。

調試參數:

參數及其默認值 描述
-XX:-CITime 打印消耗在JIT編譯的時間
-XX:ErrorFile=./hs_err_pid<pid>.log 保存錯誤日志或者數據到文件中
-XX:-ExtendedDTraceProbes 開啟solaris特有的dtrace探針
-XX:HeapDumpPath=./java_pid<pid>.hprof 指定導出堆信息時的路徑或文件名
-XX:+HeapDumpOnOutOfMemoryError 當首次遭遇OOM時導出此時堆中相關信息
-XX:OnError="<cmd args>;<cmd args>" 出現致命ERROR之后運行自定義命令
-XX:OnOutOfMemoryError="<cmd args>;<cmd args>" 當首次遭遇OOM時執行自定義命令
-XX:-PrintClassHistogram 遇到Ctrl-Break后打印類實例的柱狀信息,與jmap -histo功能相同
-XX:-PrintConcurrentLocks 遇到Ctrl-Break后打印並發鎖的相關信息,與jstack -l功能相同
-XX:-PrintCommandLineFlags 打印在命令行中出現過的標記
-XX:-PrintCompilation 當一個方法被編譯時打印相關信息
-XX:-PrintGC 每次GC時打印相關信息
-XX:-PrintGC Details 每次GC時打印詳細信息
-XX:-PrintGCTimeStamps 打印每次GC的時間戳
-XX:-TraceClassLoading 跟蹤類的加載信息
-XX:-TraceClassLoadingPreorder 跟蹤被引用到的所有類的加載信息
-XX:-TraceClassResolution 跟蹤常量池
-XX:-TraceClassUnloading 跟蹤類的卸載信息
-XX:-TraceLoaderConstraints 跟蹤類加載器約束的相關信息

當系統出現問題的時候,又不能使用外部跟蹤工具(比如JProfiler……)的情況下,以上的這些參數就會發揮重大作用了,比如dump堆信息、打印並發鎖……

 

參數匯總

不管是YGC還是Full GC,GC過程中都會對導致程序運行中中斷,正確的選擇不同的GC策略,調整JVM、GC的參數,可以極大的減少由於GC工作,而導致的程序運行中斷方面的問題,進而適當的提高Java程序的工作效率。

但是調整GC是以個極為復雜的過程,由於各個程序具備不同的特點,如:web和GUI程序就有很大區別(Web可以適當的停頓,但GUI停頓是客戶無法接受的),而且由於跑在各個機器上的配置不同(主要cup個數,內存不同),

所以使用的GC種類也會不同(如何選擇見GC種類及如何選擇)。本文將注重介紹JVM、GC的一些重要參數的設置來提高系統的性能。

       JVM內存組成及GC相關內容請見文章:JVM內存組成 GC策略&內存申請

常用JVM參數:

參數名稱 含義 默認值  
-Xms 初始堆大小 物理內存的1/64(<1GB) 默認(MinHeapFreeRatio參數可以調整)空余堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制.
-Xmx 最大堆大小 物理內存的1/4(<1GB) 默認(MaxHeapFreeRatio參數可以調整)空余堆內存大於70%時,JVM會減少堆直到 -Xms的最小限制
-Xmn 年輕代大小(1.4or lator)   注意:此處大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是不同的。
整個堆大小=年輕代大小 + 年老代大小 + 持久代大小.
增大年輕代后,將會減小年老代大小.此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8
-XX:NewSize 設置年輕代大小(for 1.3/1.4)    
-XX:MaxNewSize 年輕代最大值(for 1.3/1.4)    
-XX:PermSize 設置持久代(perm gen)初始值 物理內存的1/64 在JDK1.8以后面的版本,使用元空間(-XX:MetaspaceSize)來代替永久代 
-XX:MaxPermSize 設置持久代最大值 物理內存的1/4 在JDK1.8以后面的版本,使用元空間(-XX:MaxMetaspaceSize)來代替永久代 
-Xss

每個線程的堆棧大小

-Xss1024k等同於: -XX:ThreadStackSize=1024k

 

JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.更具應用的線程所需內存大小進行 調整.在相同物理內存下,減小這個值能生成更多的線程.但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。
一般小的應用, 如果棧不是很深, 應該是128k夠用的 大的應用建議使用256k。這個選項對性能影響比較大,需要嚴格的測試。

默認值取決於平台:

Linux/ARM (32-bit): 320 KB

Linux/i386 (32-bit): 320 KB

Linux/x64 (64-bit): 1024 KB

OS X (64-bit): 1024 KB

Oracle Solaris/i386 (32-bit): 320 KB

Oracle Solaris/x64 (64-bit): 1024 KB

-XX:ThreadStackSize 設置線程堆棧大小   (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.]
-XX:NewRatio 年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)   -XX:NewRatio=4表示年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
Xms=Xmx並且設置了Xmn的情況下,該參數不需要進行設置。
-XX:SurvivorRatio Eden區與Survivor區的大小比值   默認為8,則兩個Survivor區與一個Eden區的比值為2:8,一個Survivor區占整個年輕代的1/10
-XX:+UseLargePages 使用大頁面內存    
-XX:LargePageSizeInBytes 設置用於Java堆的大頁面尺寸   =128m,內存頁的大小不可設置過大, 會影響Perm的大小
-XX:+UseFastAccessorMethods 原始類型的快速優化   1.7以后不建議使用,1.6之前默認打開
-XX:+UseFastEmptyMethods 優化空方法   1.7以后不建議使用,1.6之前默認打開
-XX:MaxTenuringThreshold 對象存在於新生代所能經歷Minor GC的最大次數 並行(吞吐量)收集器的默認值為15,而CMS收集器的默認值為6 如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年老代. 對於年老代比較多的應用,可以提高效率.如果將此值設置為一個較大值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活 時間,增加在年輕代即被回收的概率
-XX:PretenureSizeThreshold 超出該大小的對象直接在老年代分配 0 單位字節 新生代采用Parallel Scavenge GC時無效
另一種直接在舊生代分配的情況是大的數組對象,且數組中無外部引用對象.
-XX:+AggressiveOpts 加快編譯    
-XX:+UseBiasedLocking 鎖機制的性能改善    
-Xnoclassgc 禁用對類的垃圾回收   禁用類的垃圾收集(GC)。這可以節省一些GC時間,從而縮短應用程序運行期間的中斷。當您在啟動時指定-Xnoclassgc時,應用程序中的類對象將在GC期間保持不變,並且始終被視為活動的。這會導致更多的內存被永久占用,如果不小心使用,會引發內存不足異常。
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空閑空間中SoftReference的存活時間 1s 每1M空閑空間可保持的SoftReference對象生存的時長(單位ms)。這個參數就是一個常量,默認值1000
-XX:TLABWasteTargetPercent TLAB占eden區的百分比 1%  
-XX:+CollectGen0First FullGC時是否先YGC false  
-XX:+DisableExplicitGC 關閉System.gc()   這個參數需要嚴格的測試
-XX:MaxMetaspaceSize 元空間的最大值 沒有限制  jdk1.8
-XX:MetaspaceSize 設置觸發元空間Full GC的閾值  21M(64位服務器)

jdk1.8,指Metaspace擴容時觸發FullGC的初始化閾值,也是最小的閾值。

Metaspace使用的是本地內存,而不是堆內存。

-XX:MaxHeapFreeRatio GC后java堆中空閑量空間的最大占比  70% 如果可用堆空間高於此值,則堆將被縮小
-XX:MinHeapFreeRatio GC后java堆中空閑量空間的最小占比  40% 如果可用堆空間低於此值,則堆將被擴展
-XX:MaxDirectMemorySize 最大堆外內存 64M 當Direct ByteBuffer分配的堆外內存到達指定大小后,即觸發Full GC。注意該值是有上限的,默認是64M,最大為sun.misc.VM.maxDirectMemory()

並行收集器相關參數:

-XX:+UseParallelGC 使用parallel 和 parallel old 收集器  

JDK1.8默認就是以下組合-XX:+UseParallelGC 新生代使用ParallelScavenge,老年代使用ParallelOld

-XX:+UseParNewGC 設置年輕代為ParNew收集器(並行收集器)  禁用狀態 設置該-XX:+UseConcMarkSweepGC選項時,它將自動啟用。
-XX:ParallelGCThreads 並行收集器的線程數   此值最好配置與處理器數目相等 同樣適用於CMS
-XX:+UseParallelOldGC 老年代垃圾收集方式為並行收集(Parallel Compacting)   這個是JAVA 6出現的參數選項
-XX:MaxGCPauseMillis 每次年輕代垃圾回收的最長時間(最大暫停時間)  200ms

VM將調整Java堆大小和其他與GC相關的參數,以使GC引起的暫停時間短於設定的毫秒,盡可能地保證內存回收花費時間不超過設定值。

請注意,這可能會導致VM降低整體吞吐量(吞吐量=運行用戶代碼時間/VM總運行時間),並且在某些情況下,VM將無法達到所需的暫停時間目標。

默認情況下,VM沒有暫停時間目標值。GC的暫停時間主要取決於堆中實時數據的數量與實時數據量。

該參數應謹慎使用。太小的值將導致系統花費過多的時間進行垃圾回收。原因是為滿足最大暫停時間,VM將設置更小的堆,以存儲相對少量的對象,來提升回收速率,會導致更高頻率的GC。

-XX:+UseAdaptiveSizePolicy 自動選擇年輕代區大小和相應的Survivor區比例 啟用 設置此選項后,並行收集器會自動選擇年輕代區大小和相應的Survivor區比例,以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用並行收集器時,一直打開.
-XX:GCTimeRatio 垃圾收集時間占總時間的比率  

表示希望在GC花費不超過應用程序執行時間的1/(1+n),n為大於0小於100的整數。

換句話說,此參數的值表示運行用戶代碼時間是GC運行時間的n倍。

舉個官方的例子,參數設置為19,那么GC最大花費時間的比率=1/(1+19)=5%,程序每運行100分鍾,允許GC停頓共5分鍾,其吞吐量=1-GC最大花費時間比率=95%

默認情況下,VM設置此值為99,運行用戶代碼時間是GC停頓時間的99倍,即GC最大花費時間比率為1%

-XX:+ScavengeBeforeFullGC Full GC前調用YGC true Do young generation GC prior to a full GC. (Introduced in 1.4.1.)

CMS相關參數:

-XX:+UseConcMarkSweepGC 使用CMS垃圾收集器   使用parNew 和 CMS 收集器(啟用此選項后,會自動設置-XX:+UseParNewGC選項)。測試中配置這個以后,-XX:NewRatio=4的配置失效了,原因不明.所以,此時年輕代大小最好用-Xmn設置.???
-XX:+AggressiveHeap     試圖是使用大量的物理內存
長時間大內存使用的優化,能檢查計算資源(內存, 處理器數量)
至少需要256MB內存
大量的CPU/內存, (在1.4.1在4CPU的機器上已經顯示有提升)
-XX:+CMSScavengeBeforeRemark 在FullGC前啟動一次MinorGC   目的在於減少老年代對年輕代的引用,降低CMSGC的標記階段時的開銷
-XX:CMSFullGCsBeforeCompaction 多少次fullGC后進行壓縮一次(碎片整理)  0 由於並發收集器不對內存空間進行壓縮,整理,所以運行一段時間以后會產生"碎片",使得運行效率降低.此值設置運行多少次GC以后對內存空間進行壓縮,整理.
-XX:+CMSParallelInitialMarkEnabled 使用多線程進行初始標記,降低標記停頓 默認單線程 可以減少STW
-XX:+CMSParallelRemarkEnabled 使用多線程進行重新標記,降低標記停頓 默認單線程 可以減少STW
-XX+UseCMSCompactAtFullCollection 在FULL GC的時候,開啟內存碎片合並整理過程   CMS是不會移動內存的, 因此, 這個非常容易產生碎片, 導致內存不夠用, 因此, 內存的壓縮這個時候就會被啟用。 增加這個參數是個好習慣。
可能會影響性能,但是可以消除碎片
-XX:CMSInitiatingOccupancyFraction=70 使用cms作為垃圾回收,使用70%后開始CMS收集 92 為了保證不出現promotion failed(見下面介紹)錯誤,該值的設置需要滿足以下公式CMSInitiatingOccupancyFraction計算公式
-XX:+UseCMSInitiatingOccupancyOnly     這個參數搭配-XX:CMSInitiatingOccupancyFraction使用,表示不是要一直使用它的比例觸發FullGC,如果設置則只會在第一次FullGC的時候使用-XX:CMSInitiatingOccupancyFraction的值,之后會進行自動調整。
-XX:CMSInitiatingPermOccupancyFraction 設置Perm Gen使用到達多少比率時觸發 92  
-XX:+CMSIncrementalMode 設置為增量模式   用於單CPU情況
-XX:+CMSClassUnloadingEnabled      
-XX:+ExplicitGCInvokesConcurrent 改變System.gc()的行為,讓其從full gc –> CMS GC  

如果系統使用堆外內存,比如用到了Netty的DirectByteBuffer類,那么當想回收堆外內存的時候,需要調用system.gc(),而這個方法將進行full gc,整個應用將會停頓,如果是使用CMS垃圾收集器,那么可以設置此參數。

注意:設置了ExplicitGCInvokesConcurrent,那就不要設置DisableExplicitGC參數來禁掉System.gc()

輔助信息:

-XX:+PrintGC  打印GC信息  

輸出形式:

[GC 118250K->113543K(130112K), 0.0094143 secs]
[Full GC 121376K->10414K(130112K), 0.0650971 secs]

-XX:+PrintGCDetails  打印GC詳細信息  

輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]
[GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

-XX:+PrintGCTimeStamps  打印GC過程中具體的時間戳    
-XX:+PrintGC:PrintGCTimeStamps     可與-XX:+PrintGC -XX:+PrintGCDetails混合使用
輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
-XX:+PrintGCApplicationStoppedTime 打印垃圾回收期間程序暫停的時間   輸出形式:Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中斷的執行時間   輸出形式:Application time: 0.5291524 seconds
-XX:+PrintHeapAtGC 打印GC前后的詳細堆棧信息    
-Xloggc:filename 把相關日志信息記錄到文件以便分析    

-XX:+PrintClassHistogram

遇到Ctrl-Break后打印類實例的柱狀信息,與jmap -histo功能相同    
-XX:+PrintTLAB 查看TLAB空間的使用情況    
-XX:+PrintTenuringDistribution

查看對像存在於新生代所經歷 Minor GC次數的閾值

 

Desired survivor size 1048576 bytes, new threshold 7 (max 15)
new threshold 7即標識新的存活周期的閾值為7。

-XX:PrintReferenceGC

打印軟引用、弱引用、虛引用和Finallize隊列

   
-XX:ErrorFile 指定發生不可恢復的錯誤時將錯誤數據寫入的路徑和文件名  

默認情況下,此文件在當前工作目錄中創建,並命名為hs_err_pid.log,其中pid是導致錯誤的進程的標識符。

以下示例顯示了如何將錯誤日志設置為/var/log/java/java_error.log:

-XX:ErrorFile = / var / log / java / java_error.log

-XX:OnOutOfMemoryError 發生OutOfMemoryError第一次引發異常時運行的自定義命令或一系列用分號分隔的命令。   -XX:OnOutOfMemoryError="C:\Program Files\Java\jdk1.8.0_152\bin\jconsole.exe"
-XX:+HeapDumpOnOutOfMemoryError 開啟堆轉儲 禁用 java.lang.OutOfMemoryError引發異常時,使用堆分析器(HPROF)啟用將Java堆轉儲到當前目錄中的文件的功能。您可以使用該-XX:HeapDumpPath選項顯式設置堆轉儲文件的路徑和名稱。
-XX:HeapDumpPath 設置堆轉儲的路徑和文件名   設置-XX:+HeapDumpOnOutOfMemoryError選項時,設置用於寫入由堆分析器(HPROF)提供的堆轉儲的路徑和文件名。默認情況下,在當前工作目錄中創建該文件,並將其命名為java_pid.hprof,其中pid是導致錯誤的進程的標識符。

GC性能方面的考慮

       對於GC的性能主要有2個方面的指標:吞吐量throughput(工作時間不算gc的時間占總的時間比)和暫停pause(gc發生時app對外顯示的無法響應)。

1. Total Heap

       默認情況下,vm會增加/減少heap大小以維持free space在整個vm中占的比例,這個比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。

一般而言,server端的app會有以下規則:

  • 對vm分配盡可能多的memory;
  • 將Xms和Xmx設為一樣的值。如果虛擬機啟動時設置使用的內存比較小,這個時候又需要初始化很多對象,虛擬機就必須重復地增加內存。
  • 處理器核數增加,內存也跟着增大。

2. The Young Generation

       另外一個對於app流暢性運行影響的因素是young generation的大小。young generation越大,minor collection越少;但是在固定heap size情況下,更大的young generation就意味着小的tenured generation,就意味着更多的major collection(major collection會引發minor collection)。

       NewRatio反映的是young和tenured generation的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,將這兩個值設為一樣就固定了young generation的大小(同Xms和Xmx設為一樣)。

       如果希望,SurvivorRatio也可以優化survivor的大小,不過這對於性能的影響不是很大。SurvivorRatio是eden和survior大小比例。

一般而言,server端的app會有以下規則:

  • 首先決定能分配給vm的最大的heap size,然后設定最佳的young generation的大小;
  • 如果heap size固定后,增加young generation的大小意味着減小tenured generation大小。讓tenured generation在任何時候夠大,能夠容納所有live的data(留10%-20%的空余)。

 

經驗&&規則

    1. 年輕代大小選擇
      • 響應時間優先的應用:盡可能設大,直到接近系統的最低響應時間限制(根據實際情況選擇).在此種情況下,年輕代收集發生的頻率也是最小的.同時,減少到達年老代的對象.
      • 吞吐量優先的應用:盡可能的設置大,可能到達Gbit的程度.因為對響應時間沒有要求,垃圾收集可以並行進行,一般適合8CPU以上的應用.
      • 避免設置過小.當新生代設置過小時會導致:1.YGC次數更加頻繁 2.可能導致YGC對象直接進入舊生代,如果此時舊生代滿了,會觸發FGC.
    2. 老年代大小選擇
      1. 響應時間優先的應用:年老代使用並發收集器,所以其大小需要小心設置,一般要考慮並發會話率和會話持續時間等一些參數.如果堆設置小了,可以會造成內存碎 片,高回收頻率以及應用暫停而使用傳統的標記清除方式;如果堆大了,則需要較長的收集時間.最優化的方案,一般需要參考以下數據獲得:
        並發垃圾收集信息、持久代並發收集次數、傳統GC信息、花在年輕代和年老代回收上的時間比例。
      2. 吞吐量優先的應用:一般吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代.原因是,這樣可以盡可能回收掉大部分短期對象,減少中期的對象,而年老代盡存放長期存活對象.
    3. 較小堆引起的碎片問題
      因為年老代的並發收集器使用標記,清除算法,所以不會對堆進行壓縮.當收集器回收時,他會把相鄰的空間進行合並,這樣可以分配給較大的對象.但是,當堆空間較小時,運行一段時間以后,就會出現"碎片",如果並發收集器找不到足夠的空間,那么並發收集器將會停止,然后使用傳統的標記,清除方式進行回收.如果出現"碎片",可能需要進行如下配置:
      -XX:+UseCMSCompactAtFullCollection:使用並發收集器時,開啟對年老代的壓縮.
      -XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這里設置多少次Full GC后,對年老代進行壓縮
    4. 用64位操作系統,Linux下64位的jdk比32位jdk要慢一些,但是吃得內存更多,吞吐量更大
    5. XMX和XMS設置一樣大,MaxPermSize和MinPermSize設置一樣大,這樣可以減輕伸縮堆大小帶來的壓力
    6. 使用CMS的好處是用盡量少的新生代,經驗值是128M-256M, 然后老生代利用CMS並行收集, 這樣能保證系統低延遲的吞吐效率。 實際上cms的收集停頓時間非常的短,2G的內存, 大約20-80ms的應用程序停頓時間
    7. 系統停頓的時候可能是GC的問題也可能是程序的問題,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多問題。(相關工具的使用方法將在后面的blog中介紹)
    8. 仔細了解自己的應用,如果用了緩存,那么年老代應該大一些,緩存的HashMap不應該無限制長,建議采用LRU算法的Map做緩存,LRUMap的最大長度也要根據實際情況設定。
    9. 采用並發回收時,年輕代小一點,年老代要大,因為年老大用的是並發回收,即使時間長點也不會影響其他程序繼續運行,網站不會停頓
    10. JVM參數的設置(特別是 –Xmx –Xms –Xmn -XX:SurvivorRatio  -XX:MaxTenuringThreshold等參數的設置沒有一個固定的公式,需要根據PV old區實際數據 YGC次數等多方面來衡量。為了避免promotion faild可能會導致xmn設置偏小,也意味着YGC的次數會增多,處理並發訪問的能力下降等問題。每個參數的調整都需要經過詳細的性能測試,才能找到特定應用的最佳配置。

 

本人生產使用配置

  • CMS
-Xms1g -Xmx1g -Xmn512m -Xss256K -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:SoftRefLRUPolicyMSPerMB=0 
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=8 -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSScavengeBeforeRemark -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSParallelRemarkEnabled
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$file_path/logs/sas/sas.memory.dump -Xloggc:$file_path/logs/sas/sas.gc.log
  • G1
-Xms1g -Xmx1g -Xmn512m -Xss256K -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:SoftRefLRUPolicyMSPerMB=0 
-XX:+UseG1GC -XX:MaxGCPauseMillis=400
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$file_path/logs/sas/sas.memory.dump -Xloggc:$file_path/logs/sas/sas.gc.log

注:內存大小取決於使用服務器的資源配置

 

 

引用:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM