一.HeapSize OOM(堆空間內存溢出)
A.eg:List.add(" ")在一個死循環中不斷的調用add卻沒有remove。
B.並發導致。
解決方法有:1.代碼提速。這樣可以使得相同對象的生存時間更短。更快被GC。
2.I/O操作時候,objecft=null可以輔助GC,一旦方法脫離了作用域,相應的局部變量應用就會被注銷。
3.程序跑的飛快,還是出現OOM,考慮到去修改參數配置。
eg:堆的大小,堆空間的大小,堆空間要設置的足夠大(相對),如果太大,發生FULL GC會很恐怖
4.內存可能在某些情況增加幾十字節空間但未能釋放,每次被GC,很老的對象被GC的較慢。
eg:Session中放數據,Session回話消失才會被注銷,但是會話要很長的時間才會被注銷。
不斷的FULLGC就是不拋出OOM的現象,出現這種現象通常是一些藏匿的Bug或配置導致。
eg:Tomcat的session導致,session信息保存在全局的currentHashMap中,大量的HTTPClient訪問創建的臨時session。
但並保存系統中為之分配的SessionKey中和相關的Cookies信息,導致每次請求都創建session(幾十個字節),一般看不出來,是一個堆積如山的過程。
二.PermGen OOM(永久代內存溢出)
A.常量池(JDK1.6,JDK1.7以后常量池不會放在永久代中了。)
string常量對象會在常量池(包含類名,方法名,屬性名等信息)中以hash方式存儲和訪問,hash表默認的大小為1009,當string過多時,可以通過修改-xx:stringtableSize參數來增加Hash元素的個數,減少Hash沖突。
eg:不斷的循環調用string中的intern()方法,就會導致OOM.
B.class加載
由於class被卸載的條件十分的苛刻,這個class所對應的classLoader下面所有的class都沒有活對象的應用才會被卸載。
解決方法:在每次CGlib動態創建時,都重新給它設置一個classLoader,這樣在運行代碼就不會出現OOM,會發現大量的class被卸載。
三.DirectBuffer OOM(直接內存內存溢出)
Java中普通I/O用輸入/輸出流方式實現,輸入流InputStream(終端—>直接內存->JVM),輸出流(JVM->直接內存->終端),這一過程中有kenel與JVM之間的拷貝(很多次),為了使用直接內存,Java是有一塊區域叫DirectBuffer,不是JavaHeap而是cHeap的一部分。
eg:設置-xx:MaxDirectMemorysize:256
分配一個ByteBufferallocateDirect(257*1024*1024)就會導致OOM。
四.StackOverflowError(棧內存溢出錯誤)
1.StackOverflowError,通常都是程序的問題,JVM對棧幀的大小設置已經很大了。
2.程序運行過程中,方法分派時,會分配frame來存放本地變量,棧,pc寄存器等信息,方法再調用方法會導致Java棧空間無止境的增長(死遞歸),Java的解決方法是:設置一個私有棧(不在堆內存,而是在NativeMemory),這個棧的空間大小,通過-Xss來設置,數量級在256K-1MB。如果使用空間超過了-Xss限制,就會出現StackOverflowError。
3.eg:死遞歸
死遞歸和死循環的區別:死循環類似於while(true)的操作,它的線程棧空間使用不會遞增。而死遞歸需要記錄退回的路徑,遞歸過程中調用方法,每個方法運行過程中的本地變量。也就是要記錄上下文信息。這些信息會隨着內容的增加,占用很大的內存空間。
死遞歸:
eg:1.組件的復用。
2.子類調用父類(復用父類的方法),父類調用子類(達到多態的效果),這中間要經過許多方法,可能形成環,進而形成死遞歸。
3.三方框架的問題。
五.其他內存溢出
A.unable to creat new native thread
原因:物理內存不夠用或者OS限制了單個進程使用的最大內存,大量的線程分配時,就有可能導致占用的Native Memory很多。
eg:死循環中創建線程並啟動,線程內部申請變量,本身不退出。而且設置Os對進程內存的限制。
B.request{} byte for {}out of swap
地址空間不夠用(不一定是物理地址,還有swap,顯卡,網卡)
C.IoException:too many open files
打開太多的文件,也可能是本地的socket打開太多,而沒有被關閉,太多沒有關閉套接字導致。
更多精彩內容請看:Java特種兵上冊,136-146頁的內容。
電子版的下載地址為:http://download.csdn.net/detail/lichunlin1994/7986285
