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