這裏向你們描述一下如何使用Tomcat配置JVM參數,Tomcat自己不能直接在計算機上運行,須要依賴於硬件基礎之上的操做系統和一個java虛擬機。您能夠選擇本身的須要選擇不一樣的操做系統和對應的JDK的版本,但仍是推薦您使用Sun公司發佈的JDK。html
jvm在client模式,進行內存回收時,會停下全部的其它工做,帶回收完畢纔去執行其它任務,在這期間eclipse就卡住了。因此適當的增長jvm申請的內存大小來減小其回收的次數甚至不回收,就會是卡的現象有明顯改善。java
主要經過如下的幾個jvm參數來設置堆內存的:程序員
-Xmx512m | 最大總堆內存,通常設置爲物理內存的1/4 |
-Xms512m | 初始總堆內存,通常將它設置的和最大堆內存同樣大,這樣就不須要根據當前堆使用狀況而調整堆的大小了 |
-Xmn192m | 年輕帶堆內存,sun官方推薦爲整個堆的3/8 |
堆內存的組成 | 總堆內存 = 年輕帶堆內存 + 年老帶堆內存 + 持久帶堆內存 |
年輕帶堆內存 | 對象剛建立出來時放在這裏 |
年老帶堆內存 | 對象在被真正會回收以前會先放在這裏 |
持久帶堆內存 | class文件,元數據等放在這裏 |
-XX:PermSize=128m | 持久帶堆的初始大小 |
-XX:MaxPermSize=128m | 持久帶堆的最大大小,eclipse默認爲256m。若是要編譯jdk這種,必定要把這個設的很大,由於它的類太多了。 |
Tomcat配置JVM參數web
Tomcat自己不能直接在計算機上運行,須要依賴於硬件基礎之上的操做系統和一個java虛擬機。您能夠選擇本身的須要選擇不一樣的操做系統和對應的 JDK的版本(只要是符合Sun發佈的Java規範的),但咱們推薦您使用Sun公司發佈的JDK。確保您所使用的版本是最新的,由於Sun公司和其它一 些公司一直在爲提升性能而對java虛擬機作一些升級改進。一些報告顯示JDK1.4在性能上比JDK1.3提升了將近10%到20%。算法
能夠給Java虛擬機設置使用的內存,可是若是你的選擇不對的話,虛擬機不會補償。可經過命令行的方式改變虛擬機使用內存的大小。以下表所示有兩個參數用來設置虛擬機使用內存的大小。緩存
參數 描述服務器
-Xms JVM初始化堆的大小多線程
-Xmx JVM堆的最大值併發
這兩個值的大小通常根據須要進行設置。初始化堆的大小執行了虛擬機在啓動時向系統申請的內存的大小。通常而言,這個參數不重要。可是有的應用程序在大負載 的狀況下會急劇地佔用更多的內存,此時這個參數就是顯得很是重要,若是虛擬機啓動時設置使用的內存比較小而在這種狀況下有許多對象進行初始化,虛擬機就必 須重複地增長內存來知足使用。dom
因爲這種緣由,咱們通常把-Xms和-Xmx設爲同樣大,而堆的最大值受限於系統使用的物理內存。通常使用數據量較大的應用程序會使用持久對象,內存使用 有可能迅速地增加。當應用程序須要的內存超出堆的最大值時虛擬機就會提示內存溢出,而且致使應用服務崩潰。所以通常建議堆的最大值設置爲可用內存的最大值 的80%。
Tomcat默承認以使用的內存爲128MB,在較大型的應用項目中,這點內存是不夠的,須要調大。
Windows下,在文件/bin/catalina.bat,Unix下,在文件/bin/catalina.sh的前面,增長以下設置:
JAVA_OPTS='-Xms【初始化內存大小】
-Xmx【可使用的最大內存】'
須要把這個兩個參數值調大。例如:
表示初始化內存爲256MB,可使用的最大內存爲512MB。
另外須要考慮的是Java提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時間和頻度。收集垃圾能夠接受的速度與應用有關,應該經過分 析實際的垃圾收集的時間和頻率來調整。若是堆的大小很大,那麼徹底垃圾收集就會很慢,可是頻度會下降。若是你把堆的大小和內存的須要一致,徹底收集就很 快,可是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。在基準測試的時候,爲保證最好的性能,要把堆的 大小設大,保證垃圾收集不在整個基準測試的過程當中出現。
若是系統花費不少的時間收集垃圾,請減少堆大小。一次徹底的垃圾收集應該不超過3-5秒。若是垃圾收集成爲瓶頸,那麼須要指定代的大小,檢查垃圾收集的詳 細輸出,研究垃圾收集參數對性能的影響。通常說來,你應該使用物理內存的80%做爲堆大小。當增長處理器時,記得增長內存,由於分配能夠並行進行,而垃圾 收集不是並行的。
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了,還得這麼處理。
JVM內存設置原理
默認的java虛擬機的大小比較小,在對大數據進行處理時java就會報錯:java.lang.OutOfMemoryError。設置jvm內存的方法,對於單獨的.class,能夠用下面的方法對Test運行時的jvm內存進行設置。
java-Xms64m-Xmx256mTest
-Xms是設置內存初始化的大小
-Xmx是JVM內存設置中設置最大可以使用內存的大小(最好不要超過物理內存大小)
在weblogic中,能夠在startweblogic.cmd中對每一個domain虛擬內存的大小進行設置,默認的設置是在commEnv.cmd裏面。簡單介紹了JVM內存設置,下面咱們看一下JVM內存的調優。
JVM內存的調優
1.Heap設定與垃圾回收
JavaHeap分爲3個區,Young,Old和Permanent。Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象,本文不討論該區。JVM的Heap分配可使用-X參數設定,
JVM有2個GC線程。
第一個線程負責回收Heap的Young區。
第二個線程在Heap不足時,遍歷Heap,將Young區升級爲Older區。Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,由於第二個線程被迫運行會下降JVM的性能。
爲何一些程序頻繁發生GC?有以下緣由:
◆程序內調用了System.gc()或Runtime.gc()。
◆一些中間件軟件調用本身的GC方法,此時須要設置參數禁止這些GC。
◆Java的Heap過小,通常默認的Heap值都很小。
◆頻繁實例化對象,Release對象。此時儘可能保存並重用對象,例如使用StringBuffer()和String()。
若是你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態。許多Server端的Java程序每次GC後最好能有65%的剩餘空間。
經驗之談:
1.Server端JVM最好將-Xms和-Xmx設爲相同值。爲了優化GC,最好讓-Xmn值約等於-Xmx的1/3[2]。
2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒以內完成[2]。
注意:
1.增長Heap的大小雖然會下降GC的頻率,但也增長了每次GC的時間。而且GC運行時,全部的用戶線程將暫停,也就是GC期間,Java應用程序不作任何工做。
2.Heap大小並不決定進程的內存使用量。進程的內存使用量要大於-Xmx定義的值,由於Java爲其餘任務分配內存,例如每一個線程的Stack等。
2.Stack的設定
每一個線程都有他本身的Stack。
Xss每一個線程的Stack大小
Stack的大小限制着線程的數量。若是Stack過大就好致使內存溢漏。-Xss參數決定Stack大小,例如-Xss1024K。若是Stack過小,也會致使Stack溢漏。
3.硬件環境
硬件環境也影響GC的效率,例如機器的種類,內存,swap空間,和CPU的數量。
若是你的程序須要頻繁建立不少transient對象,會致使JVM頻繁GC。這種狀況你能夠增長機器的內存,來減小Swap空間的使用[2]。
4.4種GC
第一種爲單線程GC,也是默認的GC。,該GC適用於單CPU機器。
第二種爲ThroughputGC,是多線程的GC,適用於多CPU,使用大量線程的程序。第二種GC與第一種GC類似,不一樣在於GC在收集Young區是多線程的,但在Old區和第一種同樣,仍然採用單線程。-XX:+UseParallelGC參數啓動該GC。
第三種爲ConcurrentLowPauseGC,相似於第一種,適用於多CPU,並要求縮短因GC形成程序停滯的時間。這種GC能夠在Old區的回收同時,運行應用程序。-XX:+UseConcMarkSweepGC參數啓動該GC。
第四種爲IncrementalLowPauseGC,適用於要求縮短因GC形成程序停滯的時間。這種GC能夠在Young區回收的同時,回收一部分Old區對象。-Xincgc參數啓動該GC。
4種GC的具體描述參見[3]。關於JVM內存設置的內容就介紹到這裏,請關注本節其餘相關報道。