tomcat內存溢出解決

首先了解一下JVM內存管理的機制。

1)堆(Heap)和非堆(Non-heap)內存

 按照官方的說法:“Java 虛擬機具有一個堆,堆是運行時數據區域,所有類實例和數組的內存均從此處分配。堆是在 Java 虛擬機啓動時創建的。”“在JVM中堆之外的內存稱爲非堆內存(Non-heap memory)”。
 可以看出JVM主要管理兩種類型的內存:堆和非堆。簡單來說堆就是Java代碼可及的內存,是留給開發人員使用的;非堆就是JVM留給自己用的,
 所以方法區、JVM內部處理或優化所需的內存(如JIT編譯後的代碼緩存)、每個類結構(如運行時常數池、字段和方法數據)以及方法和構造方法的代碼都在非堆內存中。 

堆內存分配

 JVM初始分配的堆內存由-Xms指定,默認是物理內存的1/64;JVM最大分配的堆內存由-Xmx指定,默認是物理內存的1/4。默認空餘堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制;
 空餘堆內存大於70%時,JVM會減少堆直到-Xms的最小限制。因此服務器一般設置-Xms、-Xmx 相等以避免在每次GC 後調整堆的大小。
 說明:如果-Xmx 不指定或者指定偏小,應用可能會導致java.lang.OutOfMemory錯誤,此錯誤來自JVM,不是Throwable的,無法用try...catch捕捉。 

非堆內存分配

 JVM使用-XX:PermSize設置非堆內存初始值,默認是物理內存的1/64;由XX:MaxPermSize設置最大非堆內存的大小,默認是物理內存的1/4。(還有一說:MaxPermSize缺省值和-server -client選項相關,
 -server選項下默認MaxPermSize爲64m,-client選項下默認MaxPermSize爲32m。這個我沒有實驗。)
 上面錯誤信息中的PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域。還沒有弄明白PermGen space是屬於非堆內存,還是就是非堆內存,但至少是屬於了。
XX:MaxPermSize設置過小會導致java.lang.OutOfMemoryError: PermGen space 就是內存益出。 
說說爲什麼會內存益出: 
(1)這一部分內存用於存放Class和Meta的信息,Class在被 Load的時候被放入PermGen space區域,它和存放Instance的Heap區域不同。 
(2)GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS 的話,就很可能出現PermGen space錯誤。
  這種錯誤常見在web服務器對JSP進行pre compile的時候。  

2)JVM內存限制(最大值)

 首先JVM內存限制於實際的最大物理內存,假設物理內存無限大的話,JVM內存的最大值跟操作系統有很大的關係。簡單的說就32位處理器雖然可控內存空間有4GB,但是具體的操作系統會給一個限制,
 這個限制一般是2GB-3GB(一般來說Windows系統下爲1.5G-2G,Linux系統下爲2G-3G),而64bit以上的處理器就不會有限制了。

2. 爲什麼有的機器我將-Xmx和-XX:MaxPermSize都設置爲512M之後Eclipse可以啓動,而有些機器無法啓動?
 通過上面對JVM內存管理的介紹我們已經瞭解到JVM內存包含兩種:堆內存和非堆內存,另外JVM最大內存首先取決於實際的物理內存和操作系統。所以說設置VM參數導致程序無法啓動主要有以下幾種原因:
1) 參數中-Xms的值大於-Xmx,或者-XX:PermSize的值大於-XX:MaxPermSize;
2) -Xmx的值和-XX:MaxPermSize的總和超過了JVM內存的最大限制,比如當前操作系統最大內存限制,或者實際的物理內存等等。說到實際物理內存這裏需要說明一點的是,
 如果你的內存是1024MB,但實際系統中用到的並不可能是1024MB,因爲有一部分被硬件佔用了。


內存溢出解決辦法

Tomcat的啓動分爲startup.bat啓動和註冊爲windows服務的啓動,下面一一說明。

1.startup.bat啓動

在tomcat_home/bin目錄下找到catalina.bat,用文本編輯器打開,加上下面一行:

set JAVA_OPTS= -Xms1024M -Xmx1024M -XX:PermSize=256M -XX:MaxNewSize=256M -XX:MaxPermSize=256M

解釋一下各個參數:

-Xms1024M:初始化堆內存大小(注意,不加M的話單位是KB)

-Xmx1029M:最大堆內存大小

-XX:PermSize=256M:初始化類加載內存池大小

-XX:MaxPermSize=256M:最大類加載內存池大小

-XX:MaxNewSize=256M:這個還不清楚哈,有知道的說聲

還有一個-server參數,是指啓動jvm時以服務器方式啓動,比客戶端啓動慢,但性能較好,大家可以自己選擇。

2.windows服務啓動

       如果你的tomcat是註冊爲windows服務並且是以服務方式啓動的,那麼上面的方法就無效了,因爲這時tomcat啓動是讀取註冊表的參數,而不是讀取批處理文件的參數,這時我們有兩種方法來設置jvm參數。

第一種比較簡單,tomcat爲我們提供了一個設置啓動參數的窗體,雙擊tomcat_home/bin目錄下的tomcat6w.exe,如圖

Tomcat啓動內存設置 - 一個人失眠 - 渴望

下方的Initial memory pool就是初始化堆內存大小,Maximun memory pool是最大堆內存大小。

而要設置Perm Gen池的大小就要在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(路徑可能有一點點差別)

Tomcat啓動內存設置 - 一個人失眠 - 渴望

修改Options的值,把剛纔上面那些參數加進去就OK了。(別忘了先備份一下註冊表)

發佈了37 篇原創文章 · 獲贊 102 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章