1. 程式人生 > >Java堆記憶體富餘卻瘋狂FullGc問題排查

Java堆記憶體富餘卻瘋狂FullGc問題排查

 剛上線了一個新的應用叢集,第二天和第三天收到了應用FullGc超過閾值的報警簡訊。但是觀察報警Java例項的jvm監控,堆記憶體僅僅用了1G多一點,還富餘近700M。很困惑,剩餘這麼多記憶體沒被使用,那麼說明老年代記憶體是充足的才對啊!

    同事提醒我是不是申請了什麼大物件,誠然,老年代只會有兩種型別的物件,1,多次Minor Gc中存活的小物件,2,大物件,即超過了PretenureSizeThreshold這個閥值直接分配到老年代的物件。一般瘋狂Full Gc的原因就是程式申請大物件導致的。這回還是跟大物件有關嗎?

    針對報警的例項程序執行jstat -gcutil 命令,拿到了這個java程序的記憶體個個代的使用百分比。

    發現P的使用率是98%,P,即 Permanent Generation,永久代。也就是說永久代的使用率已經超過了98%。於是問題明瞭了。FullGc,大家很容易想到的是Old Generation記憶體爆了導致的!但是這不是唯一的條件,永久代記憶體回收也是歸FullGc管的!於是強烈建議我們的監控介面新增永久代的監控。永久代能回收什麼呢?一,廢棄的字串常量,二,不再被引用的class物件。

再針對這個例項執行  jstat -gccapacity pid 命令,發現這個例項的永久代僅僅給了82M。82M意味著什麼,永久代的預設堆記憶體大小。

    果斷新增JVM的永久代引數,-XX:PermSize=512M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs/im.**.com/ 。順便加上堆記憶體OOM的自動dump引數。

jstat工具類:

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html