java內存溢出詳解
一、常見的java內存溢出
1、java.lang.OutOfMemmoryError : Java heap space? -- JVM Heap (jvm 堆溢出)
JVM啟動時自動設置JVM Heap的值,其初始空間(即 -Xms)是物理內存的1/64,最大空間(-Xms)不可超過物理內存。
可利用JVM提供的 -Xmn -Xms -Xmx等選項進行設置。
Heap的大小是Young Generation(新生代)和Tenured Generation(老生代)之和。
在JVM中若98%用于GC,那可用的Heap size不足2%時,就會拋出異常。
解決之道:手動設置 JVM Heap的大小。
2、java.lang.OutOfMemoryError : PermGen space -- PermGen space溢出
Permanent Generation space(永生代):指內存的永久保存區域。
此塊內存主要是被JVM存放Class和Meta信息的。Class在被Load時被放入PermGen space區域,它和存放Instance的Heap區域不同,sun的GC不會在主程序運行期對PermGen space進行清理,所以若載入很多的Class,就可能出現PermGen space溢出。
解決之道:手動設置MaxPermSize的大小
3、java.lang.StackOverflowError? -- 棧溢出
JVM依然像C和Pascal一樣,采用棧式的虛擬機。函數的調用過程都體現在堆棧和退棧上。調用構造函數的“層”太多,會把棧區溢出的。
一般來說,棧區遠遠小于堆區,因函數調用過程往往不會多于上千層的,而即便每個函數調用需要1K,那么棧區也不過是需要1MB的空間。
通常棧的大小是1-2MB
解決之道:修改程序。
二、實際環境中的解決方法
在生產環境中tomcat內存設置不好,會出現JVM的內存溢出
1、Linux下的tomcat
修改 TOMCAT_HOME/bin/catalina.sh
位置:cygwin=false前
JAVA_OPTS="-server -Xms256 -Xmx512m -XX:PermSize=64M -XX:MaxPermSize=128m"
2、window下的tomcat
因window下的tomcat啟動分為startup.bat啟動和注冊成了windows服務,以services方式啟動。r所以修改方式不同。
1)startup.bat啟動
在TOMCAT_HOME/bin下找到catalina.bat,用文本編輯器打開,并加上一行:
set JAVA_OPTS= -server -Xms1024M -Xmx1024M -XX:PermSize=256M -XX:MaxNewSize=256M -XX:MaxPermSize=256M
說明:加上 -server 是指啟動jvm時以服務器方式啟動,比客戶端啟動慢,但性能較好,可以自己選擇。
2)windows服務啟動
若tomcat是注冊成為window服務且是以服務方式啟動,那上面方法無效。因此tomcat啟動是讀取注冊表的參數,而不是讀取批處理文件參數。此時有兩種方法來設置JVM參數。
第一種:tomcat提供了一個設置啟動參數的窗體,雙擊TOMCAT_HOME/bin下的tomcat6w.exe? 如圖:
?
Initial memory pool : 指初始化堆內存大小
Maximun memory pool : 指最大堆內存大小
若要設置PermGen池的大小需在Java Option中添加如下參數設置:
Dcatalina.base=%tomcat_home%
-Dcatalina.home=%tomcat_home%
-Djava.endorsed.dirs=%tomcat_home%\endorsed
-Djava.io.tmpdir=%tomcat_home%\temp
-XX:PermSize=256M
-XX:MaxPermSize=256M
-XX:ReservedCodeCacheSize=48M
-Duser.timezone=GMT+08
(PS:網上說每一行后面不要有空格,沒試過)
第二種:打開注冊表->HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat6\Parameters\Java(路徑可能有一點點差別)
修改Options的值,把剛才上面那些參數加進去就OK了。(別忘了先備份一下注冊表)
3、若在myeclipse中啟動tomcat,上面的修改就不起作用。
需在myeclipse中修改即可:
Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK面板中的
Optional Java VM arguments中添加:-Xms256m -Xmx512m -XX:PermSize=64M -XX:MaxPermSize=128m
?
三、JVM參數說明:
-server : 一定要作為第一個參數,在多個CPU時性能佳
-Xms : java Heap初始大小。 默認為物理內存的1/64
-Xms : java Heap最大值。建議設為物理內存的一半。不可超
-XX:PermSize : 設定內存的永久保存區初始大小,缺省值:64M
-XX:MaxPermSize : 設定內存的永久保存存區最大大小,缺省值:64M
-XX:SurvivorRatio=2 : 生還者池的大小,默值:2,若垃圾回收變成了瓶頸,可嘗試定制生成池設置
-XX:NewSize : 新生成的池的初始大小 缺省值:2M
-XX:MaxNewSize : 新生成的池的最大大小。缺省值:32M
若JVM的堆的大小大于1GB,則應該配置:-XX:newSize=640m -XX:MaxNewSize=640m -XX:SurvivorRatio=16,或將堆的總大小的50%到60%分配給新生成的池。調大新對象區,減少Full GC次數。
+XX:AggressiveHeap : 會使得Xms沒有意義。這個參數讓JVM忽略Xmx參數。瘋狂地吃完一個G物理內存,再吃盡一個G的swap.
-Xss : 每個線程的Stack大小, “-Xss 15120” 這使得JBoss每增加一個線程,就會立即消耗15M內存,而最佳值應該是128K,默認值:512K
-verbose:gc : 現實垃圾收集信息
-Xloggc:gc.log : 指定垃圾收集日志文件
-Xmn : young generation的heap大小,一般設置為Xmx的1/3或1/4.
-XX:+UseParNewGC : 縮短minor收集的時間
-XX:+UseConcMarkSweepGC : 縮短major收集的時間,此選項在Heap Size比較大而且Major收集時間較長的情況下使用更合適。
-XX:userParNewGC : 可用來設置并行收集(多CPU)
-XX:ParallelGCThreads : 可用來增加并行度(多CPU)
-XX:UseParallelGC : 設置后可使用并行清除收集器(多CPU)
?
出處:http://elf8848.iteye.com/blog/378805