1. 程式人生 > >JVM調優引數簡介、調優目標及調優經驗

JVM調優引數簡介、調優目標及調優經驗

一、JVM調優引數簡介

1、 JVM引數簡介

-XX 引數被稱為不穩定引數,之所以這麼叫是因為此類引數的設定很容易引起JVM 效能上的差異,使JVM 存在極大的不穩定性。如果此類引數設定合理將大大提高JVM 的效能及穩定性。

不穩定引數語法規則:

1.布林型別引數值
        -XX:+<option> '+'表示啟用該選項
        -XX:-<option> '-'表示關閉該選項
2.數字型別引數值:
       -XX:<option>=<number> 給選項設定一個數字型別值,可跟隨單位,例如:'m'或'M'表示兆位元組;'k'或'K'千位元組;'g'或'G'千兆位元組。32K與32768是相同大小的。
3.字串型別引數值:
        -XX:<option>=<string> 給選項設定一個字串型別值,通常用於指定一個檔案、路徑或一系列命令列表。

       例如:-XX:HeapDumpPath=./dump.core

2、 JVM引數示例

配置: -Xmx4g –Xms4g –Xmn1200m –Xss512k -XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:PermSize=100m

-XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15

解析:
-Xmx4g:堆記憶體最大值為4GB。
-Xms4g:初始化堆記憶體大小為4GB 。
-Xmn1200m:設定年輕代大小為1200MB。增大年輕代後,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8。
-Xss512k:設定每個執行緒的堆疊大小。JDK5.0以後每個執行緒堆疊大小為1MB,以前每個執行緒堆疊大小為256K。應根據應用執行緒所需記憶體大小進行調整。在相同實體記憶體下,減小這個值能生成更多的執行緒。但是作業系統對一個程序內的執行緒數還是有限制的,不能無限生成,經驗值在3000~5000左右。
-XX:NewRatio=4:設定年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設定為4,則年輕代與年老代所佔比值為1:4,年輕代佔整個堆疊的1/5
-XX:SurvivorRatio=8:設定年輕代中Eden區與Survivor區的大小比值。設定為8,則兩個Survivor區與一個Eden區的比值為2:8,一個Survivor區佔整個年輕代的1/10
-XX:PermSize=100m:初始化永久代大小為100MB。
-XX:MaxPermSize=256m:設定持久代大小為256MB。

-XX:MaxTenuringThreshold=15:設定垃圾最大年齡。如果設定為0的話,則年輕代物件不經過Survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設定為一個較大值,則年輕代物件會在Survivor區進行多次複製,這樣可以增加物件再年輕代的存活時間,增加在年輕代即被回收的概論。

二、JVM調優目標

1. 何時需要做jvm調優?
      1. heap 記憶體(老年代)持續上漲達到設定的最大記憶體值;
      2. Full GC 次數頻繁;
      3. GC 停頓時間過長(超過1秒);
      4. 應用出現OutOfMemory 等記憶體異常;
      5. 應用中有使用本地快取且佔用大量記憶體空間;

      6. 系統吞吐量與響應效能不高或下降。

2. JVM調優原則

      1.多數的Java應用不需要在伺服器上進行JVM優化;

      2.多數導致GC問題的Java應用,都不是因為我們引數設定錯誤,而是程式碼問題;

      3.在應用上線之前,先考慮將機器的JVM引數設定到最優(最適合);

      4.減少建立物件的數量;

      5.減少使用全域性變數和大物件;

      6.JVM優化是到最後不得已才採用的手段;

      7.在實際使用中,分析GC情況優化程式碼比優化JVM引數更好;

3. JVM調優目標

1. GC低停頓;

      2. GC低頻率;

      3. 低記憶體佔用; 

      4. 高吞吐量;

JVM調優量化目標(示例):

1. Heap 記憶體使用率 <= 70%;

      2. Old generation記憶體使用率<= 70%;

      3. avgpause <= 1秒; 

      4. Full gc 次數0 或 avg pause interval >= 24小時 ;

      注意:不同應用,其JVM調優量化目標是不一樣的。

三、JVM調優經驗

1. JVM調優經驗總結

JVM調優的一般步驟為:

第1步:分析GC日誌及dump檔案,判斷是否需要優化,確定瓶頸問題點;

      第2步:確定JVM調優量化目標;

      第3步:確定JVM調優引數(根據歷史JVM引數來調整);

      第4步:調優一臺伺服器,對比觀察調優前後的差異;

      第5步:不斷的分析和調整,直到找到合適的JVM引數配置;

      第6步:找到最合適的引數,將這些引數應用到所有伺服器,並進行後續跟蹤。

2. JVM調優重要引數解析

注意:不同應用,其JVM最佳穩定引數配置是不一樣的。

配置: -server  

-Xms12g -Xmx12g -XX:PermSize=500m -XX:MaxPermSize=1000m -Xmn2400m -XX:SurvivorRatio=1 -Xss512k  -XX:MaxDirectMemorySize=1G 

-XX:+DisableExplicitGC -XX:CompileThreshold=8000 -XX:+UseConcMarkSweepGC  -XX:+UseParNewGC

-XX:+UseCompressedOops -XX:CMSInitiatingOccupancyFraction=60  -XX:ConcGCThreads=4

-XX:MaxTenuringThreshold=10  -XX:ParallelGCThreads=8

-XX:+ParallelRefProcEnabled  -XX:+CMSClassUnloadingEnabled  -XX:+CMSParallelRemarkEnabled

-XX:CMSMaxAbortablePrecleanTime=500 -XX:CMSFullGCsBeforeCompaction=4 

XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCMSCompactAtFullCollection 

-XX:+HeapDumpOnOutOfMemoryError  -verbose:gc  -XX:+PrintGCDetails  -XX:+PrintGCDateStamps  -Xloggc:/weblogic/gc/gc_$$.log

重要引數(可調優)解析:

-Xms12g:初始化堆記憶體大小為12GB。

-Xmx12g:堆記憶體最大值為12GB 。

-Xmn2400m:新生代大小為2400MB,包括 Eden區與2個Survivor區。

-XX:SurvivorRatio=1:Eden區與一個Survivor區比值為1:1。

-XX:MaxDirectMemorySize=1G:直接記憶體。報java.lang.OutOfMemoryError: Direct buffer memory 異常可以上調這個值。

-XX:+DisableExplicitGC:禁止執行期顯式地呼叫 System.gc() 來觸發fulll GC。

注意: Java RMI的定時GC觸發機制可通過配置-Dsun.rmi.dgc.server.gcInterval=86400來控制觸發的時間。

-XX:CMSInitiatingOccupancyFraction=60:老年代記憶體回收閾值,預設值為68。

-XX:ConcGCThreads=4:CMS垃圾回收器並行執行緒線,推薦值為CPU核心數。

-XX:ParallelGCThreads=8:新生代並行收集器的執行緒數。

-XX:MaxTenuringThreshold=10:設定垃圾最大年齡。如果設定為0的話,則年輕代物件不經過Survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設定為一個較大值,則年輕代物件會在Survivor區進行多次複製,這樣可以增加物件再年輕代的存活時間,增加在年輕代即被回收的概論。

-XX:CMSFullGCsBeforeCompaction=4:指定進行多少次fullGC之後,進行tenured區 記憶體空間壓縮。

-XX:CMSMaxAbortablePrecleanTime=500:當abortable-preclean預清理階段執行達到這個時間時就會結束。

3. 觸發Full GC的場景及應對策略

年輕代空間(包括 Eden 和 Survivor 區域)回收記憶體被稱為 Minor GC,對老年代GC稱為MajorGC,而Full GC是對整個堆來說的,在最近幾個版本的JDK裡預設包括了對永生帶即方法區的回收(JDK8中無永生帶了),出現Full GC的時候經常伴隨至少一次的Minor GC,但非絕對的。MajorGC的速度一般會比Minor GC慢10倍以上。

觸發Full GC的場景及應對策略: 

      1.System.gc()方法的呼叫,應對策略:通過-XX:+DisableExplicitGC來禁止呼叫System.gc ;

      2.老年代代空間不足,應對策略:讓物件在Minor GC階段被回收,讓物件在新生代多存活一段時間,不要建立過大的物件及陣列;

      3.永生區空間不足,應對策略:增大PermGen空間

      4.GC時出現promotionfailed和concurrent mode failure,應對策略:增大survivor space

    5.Minor GC後晉升到舊生代的物件大小大於老年代的剩餘空間,應對策略:增大Tenured space 或下調CMSInitiatingOccupancyFraction=60

      6.   記憶體持續增漲達到上限導致Full GC  ,應對策略:通過dumpheap 分析是否存在記憶體洩漏

4. Gc日誌分析工具

藉助GCViewer日誌分析工具,可以非常直觀地分析出待調優點。

可從以下幾方面來分析:

      1.Memory,分析Totalheap、Tenuredheap、Youngheap記憶體佔用率及其他指標,理論上記憶體佔用率越小越好;

      2.Pause  ,分析Gc pause、Fullgc pause、Total pause三個大項中各指標,理論上GC次數越少越好,GC時長越小越好;

5. MAT 堆記憶體分析工具

EclipseMemory Analysis Tools (MAT) 是一個分析Java堆資料的專業工具,用它可以定位記憶體洩漏的原因。

參考自以下連結內容:

https://blog.csdn.net/u011683530/article/details/51013219

https://www.cnblogs.com/God-froest/p/jvm_1_3.html