本文較為詳細(xì)的分析了JAVA程序內(nèi)存溢出問(wèn)題原因。分享給大家供大家參考。具體如下:
遇到一個(gè)線上系統(tǒng)報(bào) java.lang.OutOfMemoryError: PermGen space 錯(cuò)誤,需要定位一下問(wèn)題。很久之前到時(shí)弄過(guò)這個(gè),現(xiàn)在還真有點(diǎn)不記得了,但這個(gè)真的是一個(gè)非常有意思的問(wèn)題,值得好好研究一下。首先第一反應(yīng)當(dāng)然是加上-XX:+PrintGCDetails參數(shù)來(lái)看具體的GC日志,但是由于程序是tomcat啟動(dòng)的,擔(dān)心里面封裝的東西太多不好定位,既然在windows下面,所以還是借助可視化工具好了。
然后我們來(lái)看一下這個(gè)錯(cuò)誤的產(chǎn)生原因,在網(wǎng)上找到一段解釋,說(shuō)的很不錯(cuò),貼過(guò)來(lái)借用一下:)
PermGen space的全稱是Permanent Generation space,是指內(nèi)存的永久保存區(qū)域,這塊內(nèi)存主要是被JVM存放Class和Meta信息的,Class在被Loader時(shí)就會(huì)被放到PermGen space中,它和存放類實(shí)例(Instance)的Heap區(qū)域不同,GC(Garbage Collection)不會(huì)在主程序運(yùn)行期對(duì)PermGen space進(jìn)行清理,所以如果你的應(yīng)用中有很CLASS的話,就很可能出現(xiàn)PermGen space錯(cuò)誤,這種錯(cuò)誤常見(jiàn)在web服務(wù)器對(duì)JSP進(jìn)行pre compile的時(shí)候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過(guò)了jvm默認(rèn)的大小(4M)那么就會(huì)產(chǎn)生此錯(cuò)誤信息了。
那么我們先加大PermGen的初始內(nèi)存大小:
linux下在catalina.sh文件的開(kāi)頭加上:
windows下在catalina.bat的文件開(kāi)頭加上:
接著我們還是用可視化的內(nèi)存查看工具來(lái)定位一下具體的問(wèn)題。對(duì)于jdk6首選當(dāng)然是自帶的工具啦,比較常用的有jconsole和jvisualvm(使用后發(fā)現(xiàn)后者更強(qiáng)大,因?yàn)橛胸S富的插件支持)。這次又遇到一個(gè)比較詭異的問(wèn)題,就是分析工具打開(kāi)后居然找不到tomcat進(jìn)程(事后發(fā)現(xiàn)居然啟動(dòng)的是jre,改成jdk應(yīng)該就可以了)。
既然本地不讓連,我就遠(yuǎn)程連接得了,打開(kāi)JMX即可。
和上面一樣,在catalina.sh或catalina.bat文件的開(kāi)頭的JAVA_OPTS里面加上
啟動(dòng)程序以后用netstat查看一下端口是否正確打開(kāi),以確保遠(yuǎn)程可以連接上。
我這里偷懶了下,把a(bǔ)uthenticate關(guān)掉了,要是打開(kāi)需要設(shè)置一些權(quán)限的東西,比較麻煩。這個(gè)設(shè)置在我本地的PC機(jī)上生效,但是在服務(wù)器上居然不行,可能裝了什么軟件把端口給封了,所以我只好再犯下賤,把端口改成1000。打開(kāi)jvisualvm,點(diǎn)擊file -> add JMX connection,然后加上localhost:1000就連上了。
等連上程序以后,觀察一段時(shí)間的內(nèi)存變化狀況,我重點(diǎn)看了下Perm的情況,一直穩(wěn)定在94m的樣子,運(yùn)行一天一切正常。可能是之前設(shè)置Perm內(nèi)存大小沒(méi)有生效,因?yàn)镻erm默認(rèn)初始化是16m,最大是64m,而實(shí)際占用量確實(shí)有可能導(dǎo)致這個(gè)問(wèn)題,從目前的現(xiàn)象來(lái)看應(yīng)該是不會(huì)再出現(xiàn)這個(gè)問(wèn)題了。如果需要更進(jìn)一步定位問(wèn)題,還可以使用btrace去查看某個(gè)方法具體被調(diào)用的地方。這樣可以定位到某些方法是否按預(yù)期執(zhí)行。
希望本文所述對(duì)大家的java程序設(shè)計(jì)有所幫助。
新聞熱點(diǎn)
疑難解答
圖片精選