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