天天看點

JVM參數調優八大技巧

這裡和大家分享一下JVM參數調優的八條經驗,JVM參數調優,這是很頭疼的問題,設定的不好,JVM不斷執行FullGC,導緻整個系統變得很慢,網站停滞時間能達到10秒以上,相信通過本文的學習你對JVM參數調優有新的認識。

執行個體講解JVM參數調優的八條經驗

本文将介紹JVM參數調優,這是很頭疼的問題,設定的不好,JVM不斷執行FullGC,導緻整個系統變得很慢,網站停滞時間能達到10秒以上,這種情況如果每隔幾分鐘就來一次,自己都受不了。這種停滞在測試的時候看不出來,隻有網站PV達到數十萬每天的時候問題就暴露出來了。

要想配置好JVM參數,需要對年輕代、老年代、救助空間和永久代有一定了解,還要了解JVM記憶體管理邏輯,最終還要根據自己的應用來做調整。關于JVM參數網上很多,也有很多提供實踐的例子,我也按照各種例子測試過,最終還是會出現問題。

經過幾個月的實踐改善,我就網站(要求無停滞時間)的JVM參數調優給出以下幾條經驗。

1.建議使用64位的作業系統,Linux下64位的JDK比32位的JDK要慢一些,但是吃的記憶體更多,吞吐量更大。

2.Xmx和Xms參數設定為一樣大,MaxPermSize和MinPermSize設定為一樣大,這樣可以減輕伸縮堆大小帶來的壓力。

3.調試的時候設定一些列印JVM參數,如-XX:+PrintClassHistogram-XX:+PrintGCDetails-XX:PrintGCTimeStamps-XX:+PrintHeapAtGC-Xloggc:log/gc.log,這樣可以從gc.log檔案裡面看出一些端倪來。

4.系統停頓的時候可能是GC的問題也可能是程式的問題,多用jmap和jstack檢視,或者killall-3java,然後檢視java控制台日志,能看出很多問題。又一次,網站突然很慢,jstack檢視,原來是自己寫的URLConnection連接配接太多沒有釋放,改一下程式就OK了。

5.仔細了解自己的應用,如果用了緩存,那麼老年代應該大一些,緩存的HashMap不應該無限制長,建議采用LRU算法的Map做緩存,LRUMap的最大長度也要根據實際情況設定。

6.垃圾回收時promotionfailed是個很頭痛的問題,一般可能是兩種原因産生,第一個原因是救助空間不夠,救助空間裡的對象還不應該被移動到年老代,但年輕代又有很多對象需要放入救助空間;第二個原因是年老代沒有足夠的空間接納來自年輕代的對象;這兩種情況都會轉向FullGC,網站停頓時間較長。第一個原因我的最終解決辦法是去掉救助空間,設定-XX:SurvivorRatio=65536-XX:MaxTenuringThreshold=0即可,第二個原因我的解決辦法是設定CMSInitiatingOccupancyFraction為某個值(假設70),這樣年老代空間到70%時就開始執行CMS,年老代有足夠的空間接納來自年輕代的對象。

7.不管怎樣,永久區還是會逐漸變滿,是以隔三差五重新開機java伺服器時必要的。

8.采用并發回收時,年輕代小一點,年老代要大,因為年老大用的是并發回收,即使時間長點也不會影響其他程式繼續運作,網站不會停頓。

我的最終配置如下(系統8G記憶體),每天幾百萬PV一點問題都沒有,網站沒有停頓,2009年網站沒有因為記憶體問題down過機。

$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT  
-server-Xms6000M-Xmx6000M-Xmn500M  
-XX:PermSize=500M-XX:MaxPermSize=500M 
-XX:SurvivorRatio=65536 
-XX:MaxTenuringThreshold=0 
-Xnoclassgc  
-XX:+DisableExplicitGC  
XX:+UseParNewGC-XX:+UseConcMarkSweepGC  
-XX:+UseCMSCompactAtFullCollection  
-XX:CMSFullGCsBeforeCompaction=0 
-XX:+CMSClassUnloadingEnabled  
-XX:-CMSParallelRemarkEnabled  
-XX:CMSInitiatingOccupancyFraction=90 
-XX:SoftRefLRUPolicyMSPerMB=0-XX:+PrintClassHistogram  
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+PrintHeapAtGC  
-Xloggc:log/gc.log";  
           

說明一下,-XX:SurvivorRatio=65536,-XX:MaxTenuringThreshold=0就是去掉了救助空間;

-Xnoclassgc禁用類垃圾回收,性能會高一點;

-XX:+DisableExplicitGC禁止System.gc(),免得程式員誤調用gc方法影響性能;

-XX:+UseParNewGC,對年輕代采用多線程并行回收,這樣收得快;

帶CMS參數的都是和并發回收相關的,不明白的可以上網搜尋;

CMSInitiatingOccupancyFraction,這個參數設定有很大技巧,基本上滿足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn就不會出現promotionfailed。在我的應用中Xmx是6000,Xmn是500,那麼Xmx-Xmn是5500兆,也就是年老代有5500兆,CMSInitiatingOccupancyFraction=90說明年老代到90%滿的時候開始執行對年老代的并發垃圾回收(CMS),這時還剩10%的空間是5500*10%=550兆,是以即使Xmn(也就是年輕代共500兆)裡所有對象都搬到年老代裡,550兆的空間也足夠了,是以隻要滿足上面的公式,就不會出現垃圾回收時的promotionfailed;

SoftRefLRUPolicyMSPerMB這個參數我認為可能有點用,官方解釋是softlyreachableobjectswillremainaliveforsomeamountoftimeafterthelasttimetheywerereferenced.

Thedefaultvalueisonesecondoflifetimeperfreemegabyteintheheap,我覺得沒必要等1秒;

網上其他介紹JVM參數的也比較多,估計其中大部分是沒有遇到promotionfailed,或者通路量太小沒有機會遇到,(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn這個公式絕對是原創,真遇到promotionfailed了,還得這麼處理。

文章來自:http://developer.51cto.com/art/201009/227078.htm