Java堆溢出
Java堆用于存儲對象實例,只要不斷地創(chuàng)建對象臼膏,并且保證GC Roots到對象之間有可達(dá)路徑來避免垃圾回收機(jī)制清除這些對象,那么在對象數(shù)量到達(dá)最大堆的容量限制后就會產(chǎn)生內(nèi)存溢出異常。
要解決Java堆溢出異常抬旺,重點是確認(rèn)異常源于內(nèi)存泄漏還是內(nèi)存溢出。
虛擬機(jī)棧和本地方法棧溢出
如果線程請求的棧深度大于虛擬機(jī)所允許的最大深度祥楣,將拋出StackOverflowError異常开财。
如果虛擬機(jī)在擴(kuò)展棧時無法申請到足夠的內(nèi)存空間,則將拋出OutOfMemoryError異常误褪。
在單個線程下责鳍,無論是由于棧太大還是虛擬機(jī)棧容量太小,當(dāng)內(nèi)存無法分配的時候兽间,虛擬機(jī)拋出的都是StackOverflowError異常历葛。
多線程情況下,通過不斷地建立線程的方式可以產(chǎn)生OutOfMemoryError異常嘀略,如果不能減少線程數(shù)或者更換64位虛擬機(jī)的情況下恤溶,只能通過減少最大堆和棧容量來換取更多線程。
StackOverflowError異常有錯誤堆椫难颍可以閱讀咒程。
方法區(qū)和運行時常量池溢出(Non-Heap)
我們可以通過-XX:PermSize=128m -XX:MaxPermSize=256m限制方法區(qū)大小,從而間接限制其中容量池的容量
當(dāng)前的很多主流框架讼育,如spring帐姻、hibernate稠集,在對類進(jìn)行增強(qiáng)時,都會使用到CGLib這類字節(jié)碼技術(shù)卖宠,增強(qiáng)的類越多巍杈,就需要越大的方法區(qū)來保證動態(tài)生成的Class可以加載如內(nèi)存。
在經(jīng)常生成大量class的應(yīng)用中扛伍,需要特別注意類的回收情況。這類場景除了CGLib字節(jié)碼增強(qiáng)和動態(tài)語言外刺洒,常見的還有大量JSP或動態(tài)產(chǎn)生JSP文件的應(yīng)用、基于OSGI的應(yīng)用等逆航。
本機(jī)直接內(nèi)存溢出
DirectMemory容量可通過-XX:MaxDirectMemorySize指定,如果不指定因俐,則默認(rèn)與Java堆最大值一樣拇惋。
由DirectMemory導(dǎo)致的內(nèi)存溢出,一個明顯的特征是在Heap Dump文件中不會看見明顯的異常抹剩,如果讀者發(fā)現(xiàn)OOM之后Dump文件很小撑帖,而程序中又直接或間接使用了NIO,那就可以考慮檢查一下是不是這方面的原因澳眷。