Tomcat非堆內存溢出

如下內容來源於網絡,參考內容連接:html

https://www.cnblogs.com/wulaijun/p/5490699.htmljava

http://blog.51cto.com/lizhenliang/1763866算法

項目測試環境,開啓Tomcat,運行一段時間以後,出現內存溢出狀況,報錯以下:網絡

OutOfMemoryError: PermGen space   非堆溢出(永久保存區域溢出)測試

首先了解Tomcat的內存機制:spa

一.Tomcat運行環境介紹操作系統

1.Tomcat自己沒法直接在計算機上運行,須要依賴硬件基礎上的操做系統和java虛擬機;server

2.java程序啓動時JVM會分配一個初始內存和最大內存給這個應用;htm

3.當應用程序用到最大內存時,就會觸發JVM作垃圾回收(GC)動做,釋放被佔用的內存;對象

4.所以想要調整java程序啓動時的初始內存和最大內存,須要向JVM申請;

5.若是初始內存大小設置太小,且此時初始化的應用對象過多,虛擬機就必須重複的加載內存來知足使用;

6.基於以上緣由,最好把初始內存(Xms)和最大內存(Xmx)設置成同樣;

7.JVM上全部的對象都在「堆區(heap)」上分配內存(也有在棧上分配內存的)

8.堆的大小是能夠動態擴展的,但「」堆「的大小受限於系統使用的物理內存,當應用程序須要的內存超出「堆」的最大值時,JVM虛擬機就會拋出內存溢出異常,而且致使應用程序崩潰;

9.基於以上緣由,建議「堆」的大小設置成物理內存的80%;

二.JVM相關基礎概念

1)JVM內存劃分分爲年輕代(young generation)、老年代(old generation)、永久代(permanent generation)

2)年輕代又分爲Eden和survivor區,survivor區由fromspace和tospace組成,Eden區佔大容量,survivor區兩個區佔小容量,默認比例爲8:2

3)堆內存(heap)=年輕代+老年代。非堆內存=永久代

4)堆內存用處:存放的是對象,垃圾收集器就是收集這些對象,而後根據算法GC算法回收。

5)非堆內存用處:JVM自己使用,存放一些類、方法、常量、屬性等。

6)年輕代:新生成的對象首先放到年輕代的Eden區中,當Eden滿時,通過GC後,還存活的對象被複制到survivor區的fromspace中,若是survivor區滿時,會再被複制到survivor區的tospace區,若是還有存活對象,就會被複制到老年代。

7)老年代:在年輕代中通過GC後還存活的對象會被複制到老年代中,當老年代空間不足時,JVM會對老年代進行徹底的垃圾回收(full GC)。若是GC以後,仍是沒法存放從survivor區複製的對象,就會出現內存溢出OOM(out of memory)

8)永久代:也稱爲方法區,存放靜態類型數據,好比類,方法,屬性等。

 

根據控制檯報錯:java.lang.OutOfMemoryError: PermGen space ---- PermGen space(永久保存區內存溢出)

permgen space全稱是permanent generation space,指內存的永久保留區域;

此內存溢出緣由是這塊內存主要被JVM存放class和meta信息,class在被load的時候被放入permgen space區域;permgen space區域與存放instance的heap區域不一樣,GC不會在主程序運行期間對permgen space進行清理;因此,若是APP會載入不少class的話,極可能會出現permgen space溢出。

解決方法:手動設置MaxPermSize大小。

總結來講:Tomcat在JVM上運行時,Tomcat可能加載了不少class,可是在運行期間GC不會回收此永久保存區內存,因此permgen space只會一直增大,直到達到指定的最大的XX:PermSize值,而後就出現了內存溢出狀況,由於是測試環境,想要在測試時讓應用穩定運行,將XX:MaxPermSize值設置稍微偏大,能夠觀察在兩次開啓Tomcat服務時間段以內大概會用到多少永久保存區的內存,而後進行設置,便可保障服務穩定運行。

在Tomcat家目錄下的bin下有個catalina.bat配置文件,在其中設置內存:

JAVA_OPTS="-server -Xms512m -Xmx2048m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=512m"

附(Tomcat自帶狀態頁面):

相關文章
相關標籤/搜索