1. 適用場景
Tomcat 運行過程遇到Caused by: java.lang.OutOfMemoryError: PermGen space或者java.lang.OutOfMemoryError: Java heap space錯誤。
2. 異常原因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)那么就會產生此錯誤信息了。
Java heap space: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值。
3. 解決辦法
修改TOMCAT_HOME/bin/catalina.sh文件:
# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true"
cygwin=false
darwin=false
加入以上紅色JAVA_OPTS行記錄后重啟tomcat服務,其中JAVA_OPTS各參數的具體數值大小須根據實際服務器物理內存大小進行分配。
4. 監控JVM
4.1 查看jdk安裝路徑可選擇的命令:
(1) # echo $JAVA_HOME
(2) # whereis java
(3) # which java (java執行路徑)
(4) # echo $PATH
本例:
4.2 查看java進程
采用jdk提供的jps(JavaVirtual Machine Process Status Tool)小工具,可查看當前Java進程。
本例:進入/usr/java/jdk1.7.0_79目錄后,執行bin/jps -v:
可看到Bootstrap 前面的數字10142即為Java進程號,同時可看到JAVA_OPTS參數生效情況。
4.3 查看JVM的GC情況
使用jstat工具查看,語法為:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]參數解釋:
*Options -選項,我們一般使用-gcutil查看GC情況
vmid -VM的進程號,即當前運行的java進程號
interval -間隔時間,單位為秒或毫秒
本例:同樣在/usr/java/jdk1.7.0_79目錄中查看java進程號10142且每隔3秒輸出1次,執行# bin/jstat -gcutil 10142 3000 :

參數說明如下:
S0 -Heap上的Survivor space 0區已使用空間的百分比
S1 -Heap上的Survivor space 1區已使用空間的百分比
E -Heap上Eden space區已使用空間的百分比
O -Heap上的Old space區已使用空間的百分比,達到100%,就是內存溢出了
P -Perm space區已使用空間的百分比,達到100%,就是內存溢出了
YGC -從應用程序啟動到采樣時發生Yang GC 的次數
YGCT -從應用程序啟動到采樣時Yang GC所用的時間【單位秒】
FGC -從應用程序啟動到采樣時Full GC的次數
FGCT -從應用程序啟動到采樣時Full GC所用的時間
GCT -從應用程序啟動到采樣時用於垃圾回收的總時間【單位秒】
通過監控O、P數值情況,再次調整JAVA_OPTS相關參數大小達到優化目的。