tomcat內存詳解--轉載部分內容

  默認的情況下,tomcat的內存設置不會太大,在一些大型項目上肯定不夠用,那麼怎麼來設置tomcat的內存呢?方法也很簡單,在catania.sh第一行設置,具體情況以下設置:(實驗環境隨手設置,請勿使用在生產環境中)


[root@zonghe bin]# cat catalina.sh|grep -v ^$|grep -v ^# |head -1
JAVA_OPTS='-Xms512m -Xmx1024m'


  這裏設置開始內存512M,最大內存1G,修改之後記得重啓tomcat,本系列文章都在linux下的設置,不講解widnows下面的設置。


   檢查一下:


[root@zonghe bin]# ps -ef|grep tomcat
root     22523     1 99 Jul08 ?        29-16:53:14 /usr/local/jdk1.6.0_43/jre/bin/java -Djava.util.logging.config.file=/usr/local/tomcat6/conf/logging.properties -Xms512m -Xmx1024m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat6/endorsed -classpath /usr/local/tomcat6/bin/bootstrap.jar -Dcatalina.base=/usr/local/tomcat6 -Dcatalina.home=/usr/local/tomcat6 -Djava.io.tmpdir=/usr/local/tomcat6/temp org.apache.catalina.startup.Bootstrap start

   從tomcat運行的進程,我們可以看見設置已經生效




下面看一下JAVA_OPTS常用哪些參數來自互聯網和書籍上

-server:一定要作爲第一個參數,在多個CPU時性能佳

-Xms:初始Heap大小,使用的最小內存,cpu性能高時此值應設的大一些

-Xmx:java heap最大值,使用的最大內存

-XX:PermSize:設定內存的永久保存區域

-XX:MaxPermSize:設定最大內存的永久保存區域

-XX:MaxNewSize:

-Xss:每個線程的Stack大小

-verbose:gc 現實垃圾收集信息

-Xloggc:gc.log 指定垃圾收集日誌文件

-Xmn:young generation的heap大小,一般設置爲Xmx的3、4分之一

提示:此選項在Heap Size 比較大而且Major收集時間較長的情況下使用更合適。

+XX:AggressiveHeap 會使得 Xms沒有意義。這個參數讓jvm忽略Xmx參數,瘋狂地吃完一個G物理內存,再吃盡一個G的swap。

-Xss:每個線程的Stack大小,“-Xss 15120” 這使得JBoss每增加一個線程(thread)就會立即消耗15M內存,而最佳值應該是128K,默認值好像是512k.

-XX:+UseConcMarkSweepGC :縮短major收集的時間 此選項在Heap Size 比較大而且Major收集時間較長的情況下使用更合適。

-XX:userParNewGC 可用來設置並行收集【多CPU】

-XX:ParallelGCThreads 可用來增加並行度【多CPU】

-XX:UseParallelGC 設置後可以使用並行清除收集器【多CPU】

-XX:SurvivorRatio=2 :生還者池的大小,默認是2,如果垃圾回收變成了瓶頸,您可以嘗試定製生成池設置


以上參數是一些常用的參數,其他更詳細的信息請搜索jvm調優》 或者參見博客下方的下載(來自百度文庫)


一般情況下,我們使用以下參數即可:

JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true"

具體內存設置還需要根據你自己的實際情況來設置,現在內存已經相對便宜了,一般tomcat服務器起碼也都有8G吧,我們線上tomcat機器全部是16G,其實也很浪費了!!


看一下某公司的設置:相關參數含義在jvm調優裏面都可以找到

JAVA_OPTS="-Djava.awt.headless=true -Xmx1536M -Xms1536M -Xmn384M -XX:PermSize=256M -XX:MaxPermSize=256M  -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC  -XX:+CMSParallelRemarkEnabled -XX:SurvivorRatio=8 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3  -XX:CMSInitiatingOccupancyFraction=60  -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/logs/tomcat/gc.log  -XX:+HeapDumpOnOutOfMemoryError"



內存設置方面的技巧某位網友的總結


  我們一般把-Xms-Xmx設爲一樣大,而堆的最大值受限於系統使用的物理內存。一般使用數據量較大的應用程序會使用持久對象,內存使用有可能迅速地增長。當應用程序需要的內存超出堆的最大值時虛擬機就會提示內存溢出,並且導致應用服務崩潰。因此一般建議堆的最大值設置爲可用JVM內存的最大值的80%


  另外需要考慮的是Java提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應用有關,應該通過分析實際的垃圾收集的時間和頻率來調整。如果堆的大小很大,那麼完全垃圾收集就會很慢,但是頻度會降低。如果你把堆的大小和內存的需要一致,完全收集就很快,但是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。在基準測試的時候,爲保證最好的性能,要把堆的大小設大,保證垃圾收集不在整個基準測試的過程中出現。


  如果系統花費很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應該不超過3-5秒。如果垃圾收集成爲瓶頸,那麼需要指定代的大小,檢查垃圾收集的詳細輸出,研究垃圾收集參數對性能的影響。一般說來,你應該使用物理內存的80%作爲堆大小。當增加處理器時,記得增加內存,因爲分配可以並行進行,而垃圾收集不是並行的。


   一個要注意的地方:建議把內存的最高值跟最低值的差值縮小,不然會浪費很多內存的,最低值加大,最高值可以隨便設,但是要根據實際的物理內存,如果內存設置太大了,比如設置了512M最大內存,但如果沒有512M可用內存,Tomcat就不能啓動,還有可能存在內存被系統上


tomcat權威指南中對內存設置的描述如下:

  堆棧設置無疑是要適當理解和設置的重要環節,過渡嚴格的內存設置要麼使tomcat運行很慢,要麼報內存溢出的錯誤信息,使工作不正常。內存設置過大,要麼因不能平均分配如此大量的內存而無法啓動jvm,要麼能啓動運行正常,但卻消耗用了超出所需的過量計算機內存,而且計算機上的其他軟件也無法運行.


個人總結:

  到底怎麼設置內存爲最合適,需要根據自己服務器程序分佈(是不是隻跑了tomcat,我們線上服務器還跑了其他應用),物理內存大小,應用程序本身需求的內存,不同的併發請求,需求的內存也不一樣。需要自己根據實際情況來不斷的微調,不斷的測試,達到一個性能最優化的參數


建議設置規則:

1.關閉圖形化參數,開啓多cpu參數(如果服務器是單u就算了)

2.在物理內存較少的情況下,且服務器只跑了tomcat應用,那麼最大內存設置只能爲物理內存的80%

3.關閉debug調試

4.在某些應用中設置Xms和Xmx爲一樣的值(具體看自己需求,是否需要堆棧跟着增長)

5.避免內存溢出的參數提前設置好


jvm的調優最好和開發一起,這方面可能開發更有經驗,開發和運維本來就是一體!




tomcat內存溢出:轉George的博客:《tomcat內存溢出總結》 我發現這篇博文寫的非常好,所以轉載了


在生產環境中tomcat內存設置不好很容易出現內存溢出。造成內存原因是不一樣的,當然處理方式也不一樣。

這裏根據平時遇到的情況和相關資料進行一個總結。常見的一般會有下面三種情況:

1.OutOfMemoryError: Java heap space

2.OutOfMemoryError: PermGen space

3.OutOfMemoryError: unable to create new native thread.

Tomcat內存溢出解決方案

對於前兩種情況,在應用本身沒有內存泄露的情況下可以用設置tomcat jvm參數來解決。(-Xms -Xmx -XX:PermSize  -XX:MaxPermSize)

最後一種可能需要調整操作系統和tomcat jvm參數同時調整才能達到目的。


第一種:是堆溢出。

在JVM中如果98%的時間是用於GC且可用的 Heap size 不足2%的時候將拋出此異常信息。

沒有內存泄露的情況下,調整-Xms -Xmx參數可以解決。

-Xms:初始堆大小

-Xmx:最大堆大小


但堆的大小受下面三方面影響:

1.相關操作系統的數據模型(32-bt還是64-bit)限制;(32位系統下,一般限制在1.5G~2G;我在2003 server 系統下(物理內存:4G和6G,jdk:1.6)測試 1612M,64爲操作系統對內存無限制。)

2.系統的可用虛擬內存限制;

3.系統的可用物理內存限制。

堆的大小可以使用 java -Xmx***M  version 命令來測試。支持的話會出現jdk的版本號,不支持會報錯。

-Xms -Xmx一般配置成一樣比較好比如set JAVA_OPTS= -Xms1024m -Xmx1024m


第二種:永久保存區域溢出

PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域。這一部分用於存放Class和Meta的信息,Class在被 Load的時候被放入PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。這種錯誤常見在web服務器對JSP進行pre compile的時候。但目前的hibernate和spring項目中也很容易出現這樣的問題。http://www.javaeye.com/topic/80620?page=1 的帖子有討論的這個問題。可能是由於這些框架會動態class,而且jvm的gc是不會清理PemGen space的,導致內存溢出。


這一個一般是加大-XX:PermSize  -XX:MaxPermSize 來解決問題。

-XX:PermSize 永久保存區域初始大小

-XX:PermSize 永久保存區域初始最大值

這一般結合第一條使用,比如 set JAVA_OPTS= -Xms1024m -Xmx1024m  -XX:PermSize=128M -XX:PermSize=256M

有一點需要注意:java -Xmx***M  version 命令來測試的最大堆內存是 -Xmx與 -XX:PermSize的 和 比如系統支持最大的jvm堆大小事1.5G,那  -Xmx1024m  -XX:PermSize=768M 是無法運行的。


第三種:無法創建新的線程。

這種現象比較少見,也比較奇怪,主要是和jvm與系統內存的比例有關。

這種怪事是因爲JVM已經被系統分配了大量的內存(比如1.5G),並且它至少要佔用可用內存的一半。有人發現,在線程個數很多的情況下,你分配給JVM的內存越多,那麼,上述錯誤發生的可能性就越大。

產生這種現象的原因如下(從這個blog中瞭解到原因:http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html):

每一個32位的進程最多可以使用2G的可用內存,因爲另外2G被操作系統保留。這裏假設使用1.5G給JVM,那麼還餘下500M可用內存。這500M內存中的一部分必須用於系統dll的加載,那麼真正剩下的也許只有400M,現在關鍵的地方出現了:當你使用Java創建一個線程,在JVM的內存裏也會創建一個Thread對象,但是同時也會在操作系統裏創建一個真正的物理線程(參考JVM規範),操作系統會在餘下的400兆內存裏創建這個物理線程,而不是在JVM的1500M的內存堆裏創建。在jdk1.4裏頭,默認的棧大小是256KB,但是在jdk1.5裏頭,默認的棧大小爲1M每線程,因此,在餘下400M的可用內存裏邊我們最多也只能創建400個可用線程。


這樣結論就出來了,要想創建更多的線程,你必須減少分配給JVM的最大內存。還有一種做法是讓JVM宿主在你的JNI代碼裏邊。

給出一個有關能夠創建線程的最大個數的估算公式:


(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

對於jdk1.5而言,假設操作系統保留120M內存:

1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads

1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads

在2000/XP/2003的boot.ini裏頭有一個啓動選項,好像是:/PAE /3G ,可以讓用戶進程最大內存擴充至3G,這時操作系統只能佔用最多1G的虛存。那樣應該可以讓JVM創建更多的線程

因此這種情況需要結合操作系統進行相關調整。

因此:我們需要結合不同情況對tomcat內存分配進行不同的診斷才能從根本上解決問題。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章