java permgen内存泄漏问题处理
來自:http://longtask.com/review/2014/06/07/java-permgen-outofmemory/
?
? ? 工作以來,第三次出現內存溢出,第一次是ThreadLocal沒有remove造成的問題;第二次是ExecutorService沒有正確的shutdown造成的問題;這一次的問題在我出手排查之前,已經知道了是permgen在不斷的增長,在permgen中主要有Class和Meta信息,常量。
????在開始階段:排除了ThreadLocal可能導致的問題;排除了Thread可能導致的問題;后面就需要從新的突破點找問題了。
???? 1:基本設置的排查
????查找日志中訪問量較大的請求的URL:
awk '{print $6}' service-digest.* |awk -F"," '{print $1 ",""1"}'|awk -F"," '{a[$1]+=$2;b[$1]++}END{for(n in a)print a[n] " " n }'|sort -n????查找日志中的調用很多的內容;依然沒有發現問題;采用webbench一個個的調用請求來模擬操作,前十名的URL沒有發現問題,后面的就沒有查看了。
?
????通過線下操作,發現也不是開始懷疑的RMI遠程調用的問題;
????針對CMS-GC,網上建議開通?-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled?,好吧,我們一開始就是開通的。參考:permgen-out-of-memory-reasons
???? 2:內存使用情況
????2.1:查看內存使用情況
jmap -heap pid????2.2:查看permsize的命令
jmap -heap `ps -ef | grep java | grep -v grep` | awk 'NR==44,NR==48'????2.3:觸發full gc :
jmap -histo:live pid???? 2.4:不斷的觸發full GC 每10分鐘觀察一下內存的變化情況
PID=`ps -ef | grep java | grep uic | awk '{print $2}'`?for((i=1;i<10000;i++));do?
jmap -histo:live ${PID} > /tmp/fullgc.log?
jmap -heap ${PID} | awk "NR==42,NR==48" >> heap.log?
echo $i?
sleep 600?
done?
????2.5:觀察一段時間后(5個小時),分析相關的permsize的內存增長情況
awk '{if(NR%7==0) print $0}' heap.log???? 3:查看perm中的情況
jmap -permstat pid????查詢的結果類似一下情況:
0x00000000ce58bb18 1 3200 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700?0x00000000cec33d48 1 3088 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700?
0x00000000ce39c8b0 1 1944 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700?
0x00000000ce8ab270 1 3104 null dead sun/reflect/DelegatingClassLoader@0x00000000f4067700?
0x00000000ceb1d108 1 3104 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700?
total = 1600 11325 60491768 N/A alive=1, dead=1599 N/A
????不是反射的問題。(dead sun/reflect/DelegatingClassLoader)
???? 4:查看JDK的相關垃圾回收情況
????我們使用了CMS GC,過程中發現的GC日志看不出任何問題。
????PS:未來我們找個時間專門討論一下CMS GC的過程,方便我們在未來的垃圾處理過程中找到更加合理的方法去處理問題。
???? 5:查看perm中的類加載情況
????在啟動的腳本中打開-verbose:class來查看運行的過程中到底多少個類被加載了。【verbose和verbose:class意義相同, 還有-verbose:gc, -verbose:jni】
JAVA_OPTS="${JAVA_OPTS} -verbose:class"????啟動腳本中把輸出內容從?/dev/null 2>&1 &?修改為?>${PWD}/jvm.log
????我們通過jvm的日志發現如下奇怪的日志:
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_249 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar][Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_250 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_251 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_252 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_253 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_254 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.BonusPointDetail$$BulkBeanByCGLIB$$5a972456_255 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
????uic.dao.point.entity.BonusPointDetail的類一直在perm中增加,每次都在復制,沒有重用,也沒有被垃圾回收。問題基本就定位到這個地方。
???? 6:找出問題的具體原因
????6.1:去掉類中的反射,發現問題沒有解決。空歡喜了一場!!!!
????6.2:反復的測試調用的頁面,發現在插入操作的過程中,會出現步驟5中perm class日志的情況。針對
INSERT INTO bonus_point_detail (<isNotEmpty property="id">id,</isNotEmpty>……gmt_created,gmt_modified)VALUES (<isNotEmpty property="id">#id#,</isNotEmpty>……now(),now())????這樣的情況,我們修改為:
INSERT INTO bonus_point_detail (id,……gmt_created,gmt_modified)VALUES (#id#,……now(),now())????后續測試一下,發現問題解決,permgen不再持續增長;當某個內容寫操作比較多的時候,直接導致permgen里面有大量的類消息,從而導致了內存溢出。
????待處理:我們將下次討論為什么不能在insert的時候使用isNotEmpty的問題。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java permgen内存泄漏问题处理的全部內容,希望文章能夠幫你解決所遇到的問題。