Tomcat本身不能直接在計算機上運行,需要依賴於操作系統和一個JAVA虛擬機。Tomcat的內存溢出本質就是JVM內存溢出,JAVA程序啟動時JVM會分配一個初始內存和最大內存給程序。當程序需要的內存超出內存的最大值時虛擬機就會提示內存溢出,並且導致應用服務崩潰。
1.Tomcat異常類型
常見的Java內存溢出有以下三種:
- 1. Java.lang.OutOfMemoryError:java heap space 堆溢出。
解釋說明:JVM在啟動的時候會自動設置JVM Heap(java堆)的值,JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置。其初始空間默認是物理內存的1/64,最大空間不可超過物理內存的1/4(Tomcat默認可以使用的內存為128MB)。JVM提供-Xmn -Xms -Xmx等選項來進行相關設置。
出錯場景:在JVM中,如果98%的時間是用於GC,且可用的Heap size不足2%時,將會出現JVM Heap溢出
解決方法:修改JVM Heap的大小。
- 2. java.lang.OutOfMemoryError:PermGen space 非堆溢出
解釋說明:PermGen space是指內存的永久保存區域。這個區域主要存放Class和Meta信息,Class在被Loader時就會被放入PermGen space。
出錯場景:常見於web服務器對JSP進行pre compile的時候, 如果你的WEB APP下都用了大量的第三方jar, 其大小超過了jvm默認的大小(4M)那么就會產生此錯誤信息了。
解決方法:修改MaxPermSize大小。建議將相同的第三方jar文件移置到tomcat/shared/lib目錄下,這樣可以減少jar 文檔重復占用內存
- 3. java.lang.OutOfMemoryError:unable to create new native thread.無法創建新的線程(較少見)
解釋說明:這種現象比較少見,主要與JVM占用系統內存的比例有關,如果JVM占用的系統內存太大,導致創建線程所需要的物理內存有限。線程的大小是一定的,從而導致線程的數量受到限制。
解決方法:結合操作系統進行相關調整,結合不同情況對tomcat內存進行分配。
2.具體解決方法
前兩種內存溢出通過設置tomcat的JVM配置進行解決。具體如下:
Linux(以1G內存為例):在%tomcat安裝路徑%/bin/catalina.sh文件中加入如下語句:
JAVA_OPTS='-server -Xms800m -Xmx800m -XX:PermSize=128m -XX:MaxPermSize=128m'
其中:“m”說明單位是MB,否則默認是KB。
設置完后,需重新啟動tomcat才生效。
1 java heap(java堆)設置
-Xms :Xms java Heap初始大小。 默認是物理內存的1/64;
-Xmx :java heap最大值。不超過物理內存的80%;
-Xmn :java heap最小值,一般設置為Xmx的4分之一;
備注:一般的要將-Xms和-Xmx選項設置為相同。
32位操作系統下JVM內存不超過2GB
2 PermGen space(永久保存區域)設置
-XX:PermSize:設定內存的永久保存區域;
-XX:MaxPermSize:設定最大內存的永久保存區域;
備注:-XX:MaxPermSize與-Xmx的總和不超過物理內存。
3 JVM其他參數:
-server/-client: 兩個參數用於設置虛擬機使用何種運行模式,放在第一個
在windows上,缺省的虛擬機類型為client模式,client模式啟動比較快,但運行時性能和內存管理效率不如server模式,通常用於客戶端應用程序。
在Linux,Solaris上缺省采用server模式。server模式啟動比client慢,但可獲得更高的運行性能。對服務器端應用,推薦采用server模式,尤其是多個CPU的系統。
-XX:NewSize 新生成的池的初始大小,缺省值為2M。
-XX:MaxNewSize 新生成的池的最大大小,缺省值為32M。
-verbose:gc 現實垃圾收集信息。
-Xloggc:gc.log 指定垃圾收集日志文件。
-XX:+UseParNewGC 縮短minor收集的時間。
-XX:+UseConcMarkSweepGC 縮短major收集的時間。
-XX:userParNewGC 可用來設置並行收集(多CPU)。
-XX:ParallelGCThreads 可用來增加並行度(多CPU)。
-XX:UseParallelGC 設置后可以使用並行清除收集器(多CPU)。
備注:查詢Tomcat的JVM內存方法:
在%tomcat安裝路徑%/conf/tomcat-users.xml中添加如下語句:
開啟tomcat后 訪問port/manager/status並輸入用戶密碼(port為自己定義的ip以及端口號)即可查看JVM參數值。