經過JVM的這些選項:Xms/Xmx/PermSize/MaxPermSize能夠牽扯出不少問題,好比性能調優等。html
說明:如下轉載沒通過實踐。java
經驗實例(參考):web
設置每一個線程的堆棧大小。JDK5.0之後每一個線程堆棧大小爲1M,之前每一個線程堆棧大小爲256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減少這個值能生成更多的線程。可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右。算法
參數的含義:數組
VM內存管理的機制:緩存
一、堆(Heap)和非堆(Non-heap)內存服務器
按照官方的說法:「Java虛擬機具備一個堆,堆是運行時數據區域,全部類實例和數組的內存均今後處分配。堆是在Java虛擬機啓動時建立的。」,「在JVM中堆以外的內存稱爲非堆內存(Non-heap memory)」。併發
能夠看出JVM主要管理兩種類型的內存:堆和非堆。簡單來講堆就是Java代碼可及的內存,是留給開發人員使用的;非堆就是JVM留給本身用的,因此方法區、JVM內部處理或優化所需的內存(如JIT編譯後的代碼緩存)、每一個類結構(如運行時常數池、字段和方法數據)以及方法和構造方法的代碼都在非堆內存中。 app
1.一、堆內存分配eclipse
JVM初始分配的堆內存由-Xms指定,默認是物理內存的1/64;JVM最大分配的堆內存由-Xmx指定,默認是物理內存的1/4。默認空餘堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制;
空餘堆內存大於70%時,JVM會減小堆直到-Xms的最小限制。所以服務器通常設置-Xms、-Xmx 相等以免在每次GC 後調整堆的大小。
說明:若是-Xmx不指定或者指定偏小,應用可能會致使java.lang.OutOfMemory錯誤,此錯誤來自JVM,不是Throwable的,沒法用try...catch捕捉。
1.二、非堆內存分配
JVM使用-XX:PermSize設置非堆內存初始值,默認是物理內存的1/64;由XX:MaxPermSize設置最大非堆內存的大小,默認是物理內存的1/4。(還有一說:MaxPermSize缺省值和-server -client選項相關,-server選項下默認MaxPermSize爲64m,-client選項下默認MaxPermSize爲32m。這個我沒有實驗。)
上面錯誤信息中的PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域。尚未弄明白PermGen space是屬於非堆內存,仍是就是非堆內存,但至少是屬於了。
XX:MaxPermSize設置太小會致使java.lang.OutOfMemoryError: PermGen space 就是內存益出。
說說爲何會內存益出:
二、JVM內存限制(最大值)
首先JVM內存限制於實際的最大物理內存,假設物理內存無限大的話,JVM內存的最大值跟操做系統有很大的關係。簡單的說就32位處理器雖然可控內存空間有4GB,可是具體的操做系統會給一個限制,這個限制通常是2GB-3GB(通常來講Windows系統下爲1.5G-2G,Linux系統下爲2G-3G),而64bit以上的處理器就不會有限制了。
爲何有的機器我將-Xmx和-XX:MaxPermSize都設置爲512M以後Eclipse能夠啓動,而有些機器沒法啓動?
經過上面對JVM內存管理的介紹咱們已經瞭解到JVM內存包含兩種:堆內存和非堆內存,另外JVM最大內存首先取決於實際的物理內存和操做系統。因此說設置VM參數致使程序沒法啓動主要有如下幾種緣由:
三、堆大小設置
JVM 中最大堆大小有三方面限制:相關操做系統的數據模型(32-bt仍是64-bit)限制;系統的可用虛擬內存限制;系統的可用物理內存限制。32位系統下,通常限制在1.5G~2G;64爲操做系統對內存無限制。我在Windows Server 2003系統,3.5G物理內存,JDK5.0下測試,最大可設置爲1478m。
3.一、典型設置:
3.1.一、java -Xmx3550m -Xms3550m -Xmn2g-Xss128k
3.1.二、java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
四、回收器選擇
JVM給了三種選擇:串行收集器、並行收集器、併發收集器,可是串行收集器只適用於小數據量的狀況,因此這裏的選擇主要針對並行收集器和併發收集器。默認狀況下,JDK5.0之前都是使用串行收集器,若是想使用其餘收集器須要在啓動時加入相應參數。JDK5.0之後,JVM會根據當前系統配置進行判斷。
4.一、吞吐量優先的並行收集器
如上文所述,並行收集器主要以到達必定的吞吐量爲目標,適用於科學技術和後臺處理等。
4.1.一、典型配置:
4.1.1.一、java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
4.1.1.二、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
4.1.1.三、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100
4.1.1.四、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
4.二、響應時間優先的併發收集器
如上文所述,併發收集器主要是保證系統的響應時間,減小垃圾收集時的停頓時間。適用於應用服務器、電信領域等。
4.2.一、典型配置:
4.2.1.一、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
4.2.1.二、java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
4.三、輔助信息
JVM提供了大量命令行參數,打印信息,供調試使用。主要有如下一些:
4.3.一、-XX:+PrintGC
輸出形式:
[GC 118250K->113543K(130112K), 0.0094143 secs]
[Full GC 121376K->10414K(130112K), 0.0650971 secs]
4.3.二、-XX:+PrintGCDetails
輸出形式:
[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]
4.3.三、-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可與上面兩個混合使用
輸出形式:
11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
4.3.四、-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中斷的執行時間。可與上面混合使用
輸出形式:
Application time: 0.5291524 seconds
4.3.五、-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期間程序暫停的時間。可與上面混合使用
輸出形式:
Total time for which application threads were stopped: 0.0468229 seconds
4.3.六、-XX:PrintHeapAtGC:打印GC先後的詳細堆棧信息
輸出形式:
34.702: [GC {Heap before gc invocations=7: def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000) eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000) from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000) to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000) tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000) the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000) compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000) the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) 34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8: def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000) eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000) from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000) to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000) tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000) the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000) compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000) the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) } , 0.0757599 secs]
4.3.七、-Xloggc:filename:與上面幾個配合使用,把相關日誌信息記錄到文件以便分析。
五、常見配置彙總
5.一、堆設置
5.二、收集器設置
5.三、垃圾回收統計信息
5.四、並行收集器設置
5.五、併發收集器設置
六、調優總結
6.一、年輕代大小選擇
6.二、年老代大小選擇
6.2.一、響應時間優先的應用:年老代使用併發收集器,因此其大小須要當心設置,通常要考慮併發會話率和會話持續時間等一些參數。若是堆設置小了,能夠會形成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;若是堆大了,則須要較長的收集時間。最優化的方案,通常須要參考如下數據得到:
減小年輕代和年老代花費的時間,通常會提升應用的效率。
6.2.二、吞吐量優先的應用:通常吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。緣由是,這樣能夠儘量回收掉大部分短時間對象,減小中期的對象,而年老代盡存放長期存活對象。
6.三、較小堆引發的碎片問題
由於年老代的併發收集器使用標記、清除算法,因此不會對堆進行壓縮。當收集器回收時,他會把相鄰的空間進行合併,這樣能夠分配給較大的對象。可是,當堆空間較小時,運行一段時間之後,就會出現「碎片」,若是併發收集器找不到足夠的空間,那麼併發收集器將會中止,而後使用傳統的標記、清除方式進行回收。若是出現「碎片」,可能須要進行以下配置:
七、調優實例
環境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G內存,dell2950服務器。
7.一、JVM調優之串行垃圾回收
也就是默認配置,完成10萬request用時153秒。JVM參數配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M
-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps";
這種配置通常在resin啓動24小時內彷佛沒有大問題,網站能夠正常訪問,但查看日誌發現,在接近24小時時,FullGC執行愈來愈頻繁,大約每隔3分鐘就有一次FullGC,每次FullGC系統會停頓6秒左右,做爲一個網站來講,用戶等待6秒恐怕太長了,因此這種方式有待改善。MaxTenuringThreshold=7表示一個對象若是在救助空間移動7次尚未被回收就放入年老代,GCTimeRatio=19表示java能夠用5%的時間來作垃圾回收,1/(1+19)=1/20=5%。
7.二、JVM調優之並行回收
完成10萬request用時117秒,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xmx2048M
-Xms2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseParallelGC-XX:ParallelGCThreads=20
-XX:+UseParallelOldGC-XX:MaxGCPauseMillis=500
-XX:+UseAdaptiveSizePolicy-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19";
並行回收我嘗試過多種組合配置,彷佛都沒什麼用,resin啓動3小時左右就會停頓,時間超過10秒。也有多是參數設置不夠好的緣由,MaxGCPauseMillis表示GC最大停頓時間,在resin剛啓動尚未執行FullGC時系統是正常的,但一旦執行FullGC,MaxGCPauseMillis根本沒有用,停頓時間可能超過20秒,以後會發生什麼我也再也不關心了,趕忙重啓resin,嘗試其餘回收策略。
7.三、JVM調優之併發回收
完成10萬request用時60秒,比並行回收差很少快一倍,是默認回收策略性能的2.5倍,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0";
這個配置雖然不會出現10秒連不上的狀況,但系統重啓3個小時左右,每隔幾分鐘就會有5秒連不上的狀況,查看gc.log,發如今執行ParNewGC時有個promotionfailed錯誤,從而轉向執行FullGC,形成系統停頓,並且會很頻繁,每隔幾分鐘就有一次,因此還得改善。UseCMSCompactAtFullCollection是表是執行FullGC後對內存進行整理壓縮,省得產生內存碎片,CMSFullGCsBeforeCompaction=N表示執行N次FullGC後執行內存壓縮。
7.四、JVM調優之增量回收
完成10萬request用時171秒,太慢了,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xincgc";
彷佛回收得也不太乾淨,並且也對性能有較大影響,不值得試。
7.五、JVM調優之併發回收的I-CMS模式
和增量回收差很少,完成10萬request用時170秒。配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+UseConcMarkSweepGC-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
-XX:CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10-XX:-TraceClassUnloading";
採用了sun推薦的參數,回收效果很差,照樣有停頓,數小時以內就會頻繁出現停頓,什麼sun推薦的參數,照樣很差使。
7.六、JVM調優之遞增式低暫停收集器
又叫什麼火車式回收,完成10萬request用時153秒,配置以下:
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+UseTrainGC";
該配置效果也很差,影響性能,因此沒試。
7.七、相比之下,仍是併發回收比較好,性能比較高,只要能解決ParNewGC(並行回收年輕代)時的promotionfailed錯誤就一切好辦了,查了不少文章,發現引發promotionfailed錯誤的緣由是CMS來不及回收(CMS默認在年老代佔到90%左右纔會執行),年老代又沒有足夠的空間供GC把一些活的對象從年輕代移到年老代,因此執行FullGC。CMSInitiatingOccupancyFraction=70表示年老代佔到約70%時就開始執行CMS,這樣就不會出現FullGC了。SoftRefLRUPolicyMSPerMB這個參數也是我認爲比較有用的,我以爲不必等1秒,因此設置成0。配置以下
$JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xms2048M
-Xmx2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-XX:+DisableExplicitGC
-XX:+UseParNewGC-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0-XX:+PrintClassHistogram
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintGCApplicationStoppedTime
-Xloggc:log/gc.log";
上面這個配置內存上升的很慢,24小時以內幾乎沒有停頓現象,最長的只停滯了0.8s,ParNewGC每30秒左右才執行一次,每次回收約0.2秒,看來問題應該暫時解決了。
參數不明白的能夠上網查,本人認爲比較重要的幾個參數是:
-Xms-Xmx-XmnMaxTenuringThresholdGCTimeRatioUse ConcMarkSweepGCCMSInitiatingOccupancyFractionSoftRefLRUPolicyMSPerMB eclipse中配置JVM參數:-Xmx1024M-Xms1000M-server-XX:PermSize=64M-XX:MaxPermSize=128m
參考:
http://technique-digest.iteye.com/blog/1123046(以上內容部分轉自此篇文章)
http://www.360doc.com/content/15/0330/12/16782314_459269672.shtml(以上部份內容轉自此篇文章)
http://www.51testing.com/html/80/n-862780.html(JVM的參數調優,解決GC回收時卡頓的問題)
http://www.importnew.com/15934.html(爲何JVM指定-Xmx參數後佔用內存會變少?)
http://www.cnblogs.com/chengxin1982/p/3818448.html
http://unixboy.iteye.com/blog/174173(以上內容部分轉自此篇文章)
http://www.cnblogs.com/koik/p/4452029.html
http://cxh61207.iteye.com/blog/1160663
http://blog.chinaunix.net/uid-26602509-id-4110150.html(Tomcat內存調優)
http://blog.csdn.net/zhushuai1221/article/details/51027024
http://developer.51cto.com/art/201201/312639.htm(調優專題頻道)
http://developer.51cto.com/art/201009/227848_all.htm(JVM調優實例,以上部份內容轉自此篇文章)
http://www.cnblogs.com/zhguang/p/Java-JVM-GC.html
http://uule.iteye.com/blog/2114697