首先需要知道,觸發(fā)JVM進(jìn)行Full GC的情況:
1、System.gc()方法的調(diào)用
2、老年代空間不足
3、永生區(qū)空間不足
Permanet Generation中存放的為一些class的信息、常量、靜態(tài)變量等數(shù)據(jù),當(dāng)系統(tǒng)中要加載的類(lèi)、反射的類(lèi)和調(diào)用的方法較多時(shí),Permanet Generation可能會(huì)被占滿(mǎn),為避免Perm Gen占滿(mǎn)造成Full GC現(xiàn)象,可采用的方法為增大Perm Gen空間或轉(zhuǎn)為使用CMS GC。
4、CMS GC時(shí)出現(xiàn)promotion failed和concurrent mode failure
5、統(tǒng)計(jì)得到的Minor GC晉升到舊生代的平均大小大于老年代的剩余空間
6、堆中分配很大的對(duì)象
那么接下來(lái)就是去逐步排查具體是什么原因造成的
- 檢查啟動(dòng)參數(shù)
- 一開(kāi)始就應(yīng)該通過(guò)pstack來(lái)看,full gc是什么地方在觸發(fā),然后反推
- 使用命令 jstat -J-Djstat.showUnsupported=true -snap [pid] 查看平均晉升空間
- jstat -gccause pid 查看gc詳細(xì)原因
常見(jiàn)經(jīng)驗(yàn):
1)Java應(yīng)用的jvm參數(shù)Xms與Xmx保持一致,避免因所使用的Java堆內(nèi)存不夠?qū)е骂l繁full gc以及full gc中因動(dòng)態(tài)調(diào)節(jié)Java堆大小而耗費(fèi)延長(zhǎng)其周期。
2)建議不要調(diào)用System.gc或者Runtime.getRuntime().gc,否則本次調(diào)用可能會(huì)成為“壓死駱駝的最后一根稻草”。當(dāng)然我們可以通過(guò)設(shè)置jvm參數(shù)禁止這種調(diào)用生效,但是除非特別有把握該參數(shù)有必要添加,否則不推薦這么設(shè)置。
3)對(duì)于需要Cache比較多內(nèi)容的場(chǎng)景而言(尤其是啟動(dòng)時(shí)既要加載的),還是要給old留有一定的空間,否則悲觀(guān)策略就要發(fā)威了