java-jvm-full gc频繁的分析及解决
生活随笔
收集整理的這篇文章主要介紹了
java-jvm-full gc频繁的分析及解决
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
返回博客列表 轉(zhuǎn)?關(guān)于施用full gc頻繁的分析及解決 ? DEC_LIU
很久前的工作日記了,移到ITeye上來(lái)。
- 發(fā)布時(shí)間:?2013/10/13 20:32?
- 閱讀:?3431?
- 收藏:?14?
- 點(diǎn)贊:?1?
- 評(píng)論:?1
很久前的工作日記了,移到ITeye上來(lái)。
現(xiàn)象
系統(tǒng)報(bào)警full gc次數(shù)過(guò)多,每2分鐘達(dá)到了5~6次,這是不正常的現(xiàn)象 在full gc報(bào)警時(shí)的gc.log如下: 在full gc報(bào)警時(shí)的jstat如下: sudo -u admin -H /opt/taobao/java/bin/jstat -gcutil `pgrep java` 2000 100 ? 此時(shí)的cpu如下(基本都是在做gc):? 將應(yīng)用重啟后,問(wèn)題解決 但是當(dāng)后臺(tái)執(zhí)行低價(jià)航線更新時(shí),過(guò)大概十幾個(gè)小時(shí)后,又出現(xiàn)上述情況!分析
當(dāng)頻繁full gc時(shí),jstack打印出堆棧信息如下: sudo -u admin -H /opt/taobao/java/bin/jstack `pgrep java` > #your file path# 可以看到的確是在跑低價(jià)信息 另外在應(yīng)用頻繁full gc時(shí)和應(yīng)用正常時(shí),也執(zhí)行了如下2種命令: sudo -u admin -H /opt/taobao/java/bin/jmap -histo `pgrep` > #your file path# sudo -u admin -H /opt/taobao/java/bin/jmap -histo:live `pgrep` > #your file path#(live會(huì)產(chǎn)生full gc) 目的是確認(rèn)以下2種信息: (1)是否存在某些引用的不正常,造成對(duì)象始終可達(dá)而無(wú)法回收(Java中的內(nèi)存泄漏) (2)是否真是由于在頻繁full gc時(shí)同時(shí)又有大量請(qǐng)求進(jìn)入分配內(nèi)存從而處理不過(guò)來(lái),造成concurrent mode failure? 下圖是在應(yīng)用正常情況下,jmap不加live,產(chǎn)生的histo信息: 下圖是在應(yīng)用正常情況下,jmap加live,產(chǎn)生的histo信息: 下圖是在應(yīng)用頻繁full gc情況下,jmap不加live和加live,產(chǎn)生的histo信息: 從上述幾個(gè)圖中可以看到: (1)在應(yīng)用正常情況下,圖中標(biāo)紅的對(duì)象是被回收的,因此不是內(nèi)存泄漏問(wèn)題 (2)在應(yīng)用頻繁full gc時(shí),標(biāo)紅的對(duì)象即使加live也是未被回收的,因上就是在頻繁full gc時(shí),同時(shí)又有大量請(qǐng)求進(jìn)入分配內(nèi)存從而處理不過(guò)來(lái)的問(wèn)題先從解決問(wèn)題的角度,看怎樣造成頻繁的full gc?
從分析CMS GC開(kāi)始
先給個(gè)CMS GC的概況: (1)young gc 可以看到,當(dāng)eden滿時(shí),young gc使用的是ParNew收集器 ParNew: 2230361K->129028K(2403008K), 0.2363650 secs解釋: 1)2230361K->129028K,指回收前后eden+s1(或s2)大小 2)2403008K,指可用的young代的大小,即eden+s1(或s2) 3)0.2363650 secs,指消耗時(shí)間 2324774K->223451K(3975872K), 0.2366810 sec解釋: 1)2335109K->140198K,指整個(gè)堆大小的變化 (heap=(young+old)+perm;young=eden+s1+s2;s1=s2=young/(survivor ratio+2)) 2)0.2366810 sec,指消耗時(shí)間 [Times: user=0.60 sys=0.02, real=0.24 secs]解釋:指用戶(hù)時(shí)間,系統(tǒng)時(shí)間,真實(shí)時(shí)間 (2)cms gc 當(dāng)使用CMS收集器時(shí),當(dāng)開(kāi)始進(jìn)行收集時(shí),old代的收集過(guò)程如下所示: a)首先jvm根據(jù)-XX:CMSInitiatingOccupancyFraction,-XX:+UseCMSInitiatingOccupancyOnly來(lái)決定什么時(shí)間開(kāi)始垃圾收集 b)如果設(shè)置了-XX:+UseCMSInitiatingOccupancyOnly,那么只有當(dāng)old代占用確實(shí)達(dá)到了-XX:CMSInitiatingOccupancyFraction參數(shù)所設(shè)定的比例時(shí)才會(huì)觸發(fā)cms gc c)如果沒(méi)有設(shè)置-XX:+UseCMSInitiatingOccupancyOnly,那么系統(tǒng)會(huì)根據(jù)統(tǒng)計(jì)數(shù)據(jù)自行決定什么時(shí)候觸發(fā)cms gc;因此有時(shí)會(huì)遇到設(shè)置了80%比例才cms gc,但是50%時(shí)就已經(jīng)觸發(fā)了,就是因?yàn)檫@個(gè)參數(shù)沒(méi)有設(shè)置的原因 d)當(dāng)cms gc開(kāi)始時(shí),首先的階段是CMS-initial-mark,此階段是初始標(biāo)記階段,是stop the world階段,因此此階段標(biāo)記的對(duì)象只是從root集最直接可達(dá)的對(duì)象 CMS-initial-mark:961330K(1572864K),指標(biāo)記時(shí),old代的已用空間和總空間 e)下一個(gè)階段是CMS-concurrent-mark,此階段是和應(yīng)用線程并發(fā)執(zhí)行的,所謂并發(fā)收集器指的就是這個(gè),主要作用是標(biāo)記可達(dá)的對(duì)象 此階段會(huì)打印2條日志:CMS-concurrent-mark-start,CMS-concurrent-mark f)下一個(gè)階段是CMS-concurrent-preclean,此階段主要是進(jìn)行一些預(yù)清理,因?yàn)闃?biāo)記和應(yīng)用線程是并發(fā)執(zhí)行的,因此會(huì)有些對(duì)象的狀態(tài)在標(biāo)記后會(huì)改變,此階段正是解決這個(gè)問(wèn)題 因?yàn)橹蟮腞escan階段也會(huì)stop the world,為了使暫停的時(shí)間盡可能的小,也需要preclean階段先做一部分工作以節(jié)省時(shí)間 此階段會(huì)打印2條日志:CMS-concurrent-preclean-start,CMS-concurrent-preclean g)下一階段是CMS-concurrent-abortable-preclean階段,加入此階段的目的是使cms gc更加可控一些,作用也是執(zhí)行一些預(yù)清理,以減少Rescan階段造成應(yīng)用暫停的時(shí)間 此階段涉及幾個(gè)參數(shù): -XX:CMSMaxAbortablePrecleanTime:當(dāng)abortable-preclean階段執(zhí)行達(dá)到這個(gè)時(shí)間時(shí)才會(huì)結(jié)束 -XX:CMSScheduleRemarkEdenSizeThreshold(默認(rèn)2m):控制abortable-preclean階段什么時(shí)候開(kāi)始執(zhí)行, 即當(dāng)eden使用達(dá)到此值時(shí),才會(huì)開(kāi)始abortable-preclean階段 -XX:CMSScheduleRemarkEdenPenetratio(默認(rèn)50%):控制abortable-preclean階段什么時(shí)候結(jié)束執(zhí)行 此階段會(huì)打印一些日志如下: CMS-concurrent-abortable-preclean-start,CMS-concurrent-abortable-preclean, CMS:abort preclean due to time XXX h)再下一個(gè)階段是第二個(gè)stop the world階段了,即Rescan階段,此階段暫停應(yīng)用線程,對(duì)對(duì)象進(jìn)行重新掃描并標(biāo)記 YG occupancy:964861K(2403008K),指執(zhí)行時(shí)young代的情況 CMS remark:961330K(1572864K),指執(zhí)行時(shí)old代的情況 此外,還打印出了弱引用處理、類(lèi)卸載等過(guò)程的耗時(shí) i)再下一個(gè)階段是CMS-concurrent-sweep,進(jìn)行并發(fā)的垃圾清理 j)最后是CMS-concurrent-reset,為下一次cms gc重置相關(guān)數(shù)據(jù)結(jié)構(gòu) (3)full gc: 有2種情況會(huì)觸發(fā)full gc,在full gc時(shí),整個(gè)應(yīng)用會(huì)暫停 a)concurrent-mode-failure:當(dāng)cms gc正進(jìn)行時(shí),此時(shí)有新的對(duì)象要進(jìn)行old代,但是old代空間不足造成的 b)promotion-failed:當(dāng)進(jìn)行young gc時(shí),有部分young代對(duì)象仍然可用,但是S1或S2放不下,因此需要放到old代,但此時(shí)old代空間無(wú)法容納此?
頻繁full gc的原因
從日志中可以看出有大量的concurrent-mode-failure,因此正是當(dāng)cms gc進(jìn)行時(shí),有新的對(duì)象要進(jìn)行old代, 但是old代空間不足造成的full gc 進(jìn)程的jvm參數(shù)如下所示: 影響cms gc時(shí)長(zhǎng)及觸發(fā)的參數(shù)是以下2個(gè): -XX:CMSMaxAbortablePrecleanTime=5000 -XX:CMSInitiatingOccupancyFraction=80 解決也是針對(duì)這兩個(gè)參數(shù)來(lái)的 根本的原因是每次請(qǐng)求消耗的內(nèi)存量過(guò)大解決
(1)針對(duì)cms gc的觸發(fā)階段,調(diào)整-XX:CMSInitiatingOccupancyFraction=50,提早觸發(fā)cms gc,就可以緩解當(dāng)old代達(dá)到80%,cms gc處理不完,從而造成concurrent mode failure引發(fā)full gc (2)修改-XX:CMSMaxAbortablePrecleanTime=500,縮小CMS-concurrent-abortable-preclean階段的時(shí)間 (3)考慮到cms gc時(shí)不會(huì)進(jìn)行compact,因此加入-XX:+UseCMSCompactAtFullCollection(cms gc后會(huì)進(jìn)行內(nèi)存的compact)和-XX:CMSFullGCsBeforeCompaction=4(在full gc4次后會(huì)進(jìn)行compact)參數(shù) 但是運(yùn)行了一段時(shí)間后,只不過(guò)時(shí)間更長(zhǎng)了,又會(huì)出現(xiàn)頻繁full gc 計(jì)算了一下heap各個(gè)代的大小(可以用jmap -heap查看): total heap=young+old=4096m perm:256m young=s1+s2+eden=2560m young avail=eden+s1=2133.375+213.3125=2346.6875m s1=2560/(10+1+1)=213.3125m s2=s1 eden=2133.375m old=1536m 可以看到eden大于old,在極端情況下(young區(qū)的所有對(duì)象全都要進(jìn)入到old時(shí),就會(huì)觸發(fā)full gc), 因此在應(yīng)用頻繁full gc時(shí),很有可能old代是不夠用的,因此想到將old代加大,young代減小 改成以下: -Xmn1920m 新的各代大小: total heap=young+old=4096m perm:256m young=s1+s2+eden=1920m young avail=eden+s1=2133.375+213.3125=1760m s1=1760/(10+1+1)=160m s2=s1 eden=1600m old=2176m 此時(shí)的eden小于old,可以緩解一些問(wèn)題 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的java-jvm-full gc频繁的分析及解决的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: shell中if 变量里包含字符串的判断
- 下一篇: MAC下安装多版本JDK和切换几种方式