【高并发】高并发环境下如何防止 Tomcat 内存溢出?一文让你看懂!!
隨著系統(tǒng)并發(fā)量越來越高,Tomcat 所占用的內(nèi)存就會越來越大,如果對 Tomcat 的內(nèi)存管理不當(dāng),則可能會引發(fā) Tomcat 內(nèi)存溢出的問題,那么,如何防止 Tomcat 內(nèi)存溢出呢?我們今天就來一起探討下這個問題。
防止 Tomcat 內(nèi)存溢出可以總結(jié)為兩個方案:一個是設(shè)置 Tomcat 啟動的初始內(nèi)存,一個是防止 Tomcat 所用的 JVM 內(nèi)存溢出。接下來,我們就分別對這兩種方案作出簡單的介紹。
設(shè)置啟動初始內(nèi)存
其初始空間(即-Xms)是物理內(nèi)存的 1/64,最大空間(-Xmx)是物理內(nèi)存的 1/4。可以利用 JVM 提供的-Xmn -Xms -Xmx 等選項可進(jìn)行設(shè)置。
實例
以下給出 1G 內(nèi)存環(huán)境下 java jvm 的參數(shù)設(shè)置參考:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "JAVA_OPTS="-server -Xms768m -Xmx768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:NewSize=192m -XX:MaxNewSize=384m"CATALINA_OPTS="-server -Xms768m -Xmx768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:NewSize=192m -XX:MaxNewSize=384m"復(fù)制代碼
Linux
在/usr/local/apache-tomcat-7.0/bin 目錄下的 catalina.sh 文件中,添加:JAVA_OPTS='-Xms512m -Xmx1024m',要加“m”說明是 MB,否則就是 KB 了,在啟動 tomcat 時會報內(nèi)存不足。
-
-Xms:初始值
-
-Xmx:最大值
-
-Xmn:最小值
Windows
在 catalina.bat 最前面加入 set JAVA_OPTS=-Xms128m -Xmx350m,如果用 startup.bat 啟動 tomcat,OK 設(shè)置生效。夠成功的分配 200M 內(nèi)存。但是如果不是執(zhí)行 startup.bat 啟動 tomcat 而是利用 windows 的系統(tǒng)服務(wù)啟動 tomcat 服務(wù),上面的設(shè)置就不生效了,就是說 set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用。上面分配 200M 內(nèi)存就 OOM 了。。windows 服務(wù)執(zhí)行的是 bin\tomcat.exe。它讀取注冊表中的值,而不是 catalina.bat 的設(shè)置。
解決辦法
修改注冊表
HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions復(fù)制代碼
原值為
-Dcatalina.home="C:\ApacheGroup\Tomcat 7.0"-Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 7.0\common\endorsed"-Xrs復(fù)制代碼
加入 -Xms300m -Xmx350m 重起 tomcat 服務(wù),設(shè)置生效。
防止所用的 JVM 內(nèi)存溢出
1.java.lang.OutOfMemoryError: Java heap space
解釋
Heap size 設(shè)置
JVM 堆的設(shè)置是指 java 程序運行過程中 JVM 可以調(diào)配使用的內(nèi)存空間的設(shè)置.JVM 在啟動的時候會自動設(shè)置 Heap size 的值,其初始空間(即-Xms)是物理內(nèi)存的 1/64,最大空間(-Xmx)是物理內(nèi)存的 1/4。可以利用 JVM 提供的-Xmn -Xms -Xmx 等選項可進(jìn)行設(shè)置。Heap size 的大小是 Young Generation 和 Tenured Generaion 之和。
提示:在 JVM 中如果 98%的時間是用于 GC 且可用的 Heap size 不足 2%的時候?qū)伋龃水惓P畔ⅰ?/p>
提示:Heap Size 最大不要超過可用物理內(nèi)存的 80%,一般的要將-Xms 和-Xmx 選項設(shè)置為相同,而-Xmn 為 1/4 的-Xmx 值。
解決方法
手動設(shè)置 Heap size
修改 TOMCAT_HOME/bin/catalina.bat,在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下代碼。
set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m復(fù)制代碼
或修改 catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"復(fù)制代碼
2.java.lang.OutOfMemoryError: PermGen space
原因
PermGen space 的全稱是 Permanent Generation space,是指內(nèi)存的永久保存區(qū)域,這塊內(nèi)存主要是被 JVM 存放 Class 和 Meta 信息的,Class 在被 Loader 時就會被放到 PermGen space 中,它和存放類實例(Instance)的 Heap 區(qū)域不同,GC(Garbage Collection)不會在主程序運行期對 PermGen space 進(jìn)行清理,所以如果你的應(yīng)用中有很 CLASS 的話,就很可能出現(xiàn) PermGen space 錯誤,這種錯誤常見在 web 服務(wù)器對 JSP 進(jìn)行 pre compile 的時候。如果你的 WEB APP 下都用了大量的第三方 jar, 其大小超過了 jvm 默認(rèn)的大小(4M)那么就會產(chǎn)生此錯誤信息了。
解決方法
手動設(shè)置 MaxPermSize 大小
修改 TOMCAT_HOME/bin/catalina.bat(Linux 下為 catalina.sh),在代碼“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m復(fù)制代碼
“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m復(fù)制代碼
catalina.sh 文件的修改如下。
Java 代碼
JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m"復(fù)制代碼
3.分析 java.lang.OutOfMemoryError: PermGen space
發(fā)現(xiàn)很多人把問題歸因于: spring,hibernate,tomcat,因為他們動態(tài)產(chǎn)生類,導(dǎo)致 JVM 中的 permanent heap 溢出 。然后解決方法眾說紛紜,有人說升級 tomcat 版本到最新甚至干脆不用 tomcat。還有人懷疑 spring 的問題,在 spring 論壇上討論很激烈,因為 spring 在 AOP 時使用 CBLIB 會動態(tài)產(chǎn)生很多類。
但問題是為什么這些王牌的開源會出現(xiàn)同一個問題呢,那么是不是更基礎(chǔ)的原因呢?tomcat 在 Q&A 很隱晦的回答了這一點,我們知道這個問題,但這個問題是由一個更基礎(chǔ)的問題產(chǎn)生。
于是有人對更基礎(chǔ)的 JVM 做了檢查,發(fā)現(xiàn)了問題的關(guān)鍵。原來 SUN 的 JVM 把內(nèi)存分了不同的區(qū),其中一個就是 permenter 區(qū)用來存放用得非常多的類和類描述。本來 SUN 設(shè)計的時候認(rèn)為這個區(qū)域在 JVM 啟動的時候就固定了,但他沒有想到現(xiàn)在動態(tài)會用得這么廣泛。而且這個區(qū)域有特殊的垃圾收回機(jī)制,現(xiàn)在的問題是動態(tài)加載類到這個區(qū)域后,gc 根本沒辦法回收!
對于以上兩個問題,我的處理是:
在 catalina.bat 的第一行增加:
set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m復(fù)制代碼
在 catalina.sh 的第一行增加:
JAVA_OPTS= -Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m復(fù)制代碼
寫在最后
如果覺得文章對你有點幫助,請微信搜索并關(guān)注「?冰河技術(shù)?」微信公眾號,跟冰河學(xué)習(xí)高并發(fā)編程技術(shù)。
最后,附上并發(fā)編程需要掌握的核心技能知識圖,祝大家在學(xué)習(xí)并發(fā)編程時,少走彎路。
?
總結(jié)
以上是生活随笔為你收集整理的【高并发】高并发环境下如何防止 Tomcat 内存溢出?一文让你看懂!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 执行git命令时出现fatal: ‘or
- 下一篇: rabbitmq接口异常函数方法_Rab