一個(gè)有意思的CMS問題

簡書 占小狼 轉(zhuǎn)載請注明原創(chuàng)出處,謝謝衙耕!

大家新年好瀑凝,愿你們在新的一年順利晉升、工資漲漲漲...

之前無意間碰到一個(gè)有趣的CMS GC問題臭杰,問題很簡單粤咪,現(xiàn)象很粗暴。

代碼

/**
 * -Xmx20m -Xms20m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC
 * -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75
 * -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC
 */
public class JVM {

    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws Exception {

        byte[] b1 = new byte[2 * _1MB];
        byte[] b2 = new byte[2 * _1MB];
        byte[] b3 = new byte[2 * _1MB];
        byte[] b4 = new byte[4 * _1MB];
        System.in.read();
    }
}

現(xiàn)象

程序運(yùn)行之后渴杆,執(zhí)行jstat -gcutils pid 1000命令寥枝,結(jié)果如下:

在JVM參數(shù)中已經(jīng)設(shè)置了-XX:+UseCMSInitiatingOccupancyOnly-XX:CMSInitiatingOccupancyFraction=75

只有在老年代的使用率達(dá)到75%時(shí)才會觸發(fā)CMS回收宪塔,可目前的現(xiàn)象是老年代使用率才60%,就開始不停的GC囊拜、不停的GC某筐、不停的GC,GC日志如下:

看這架勢冠跷,應(yīng)該是在不停的發(fā)生CMS GC了南誊。

原因查找

既然一直在觸發(fā)CMS,那問題根本因?yàn)樵谟|發(fā)CMS的條件中蜜托,之前以為只要設(shè)置了-XX:+UseCMSInitiatingOccupancyOnly參數(shù)抄囚,只有在老年代的使用率達(dá)到閾值時(shí)才會觸發(fā)。

翻了代碼之后才發(fā)現(xiàn)橄务,問題沒這么簡單幔托,觸發(fā)CMS的判斷邏輯位于CMSCollector::shouldConcurrentCollect()方法中,實(shí)現(xiàn)如下:

在設(shè)置了-XX:+UseCMSInitiatingOccupancyOnly參數(shù)的前提下蜂挪,有三種情況會觸發(fā):
1重挑、老年代當(dāng)前使用率是否達(dá)到閾值CMSInitiatingOccupancyFraction;
2、判斷當(dāng)前新生代的對象是否能夠全部順利的晉升到老年代棠涮,如果不能谬哀,就提早觸發(fā)一次老年代的收集,這是本案例中不停CMS的根本原因严肪,incremental_collection_will_fail(true)實(shí)現(xiàn)如下:

其中get_gen(0)指向當(dāng)前年輕代的堆玻粪,因?yàn)樵O(shè)置了-XX:+UseParNewGC,則年輕代的堆實(shí)現(xiàn)是ParNewGeneration诬垂,該類繼承了DefNewGeneration劲室,方法collection_attempt_is_safe()位于DefNewGeneration類中,實(shí)現(xiàn)如下:

前面2個(gè)條件先忽略结窘,看最后一個(gè)條件很洋,_next_gen指向老年代的堆,其中promotion_attempt_is_safe()實(shí)現(xiàn)如下:

傳入的參數(shù)max_promotion_in_bytes隧枫,由年輕代的used方法計(jì)算得到喉磁,eden區(qū)的使用量 + from區(qū)的使用量

size_t DefNewGeneration::used() const {
  return eden()->used()
       + from()->used();      // to() is only used during scavenge
}

其中promotion_attempt_is_safe()方法中的變量
1、available是老年代的可用內(nèi)存大小
2官脓、av_promo每次YGC時(shí)晉升到老年代對象大小的平均值

當(dāng)老年代的可用內(nèi)存大于av_promo协怒,或者大于max_promotion_in_bytes時(shí),說明下次的YGC是安全的卑笨,否則返回fasle孕暇,提早進(jìn)行一次CMS操作,釋放老年代的空間,以容納下次YGC晉升上來的對象妖滔。

到這里隧哮,本文中的例子不斷的進(jìn)行CMS GC的疑惑應(yīng)該可以解釋清楚了。

別忘了座舍,還有第三種情況:

if (CMSClassUnloadingEnabled && _permGen->should_concurrent_collect()) {
    bool res = update_should_unload_classes();
    if (res) {
      if (Verbose && PrintGCDetails) {
        gclog_or_tty->print_cr("CMS perm gen initiated");
      }
      return true;
    }
  }

前提是設(shè)置了-XX:+CMSClassUnloadingEnabled沮翔,而且_permGen永久帶的內(nèi)存使用率達(dá)到了閾值CMSInitiatingPermOccupancyFraction,默認(rèn)值是92曲秉。

即使?jié)M足上面2個(gè)條件采蚀,還需要一層判斷update_should_unload_classes()

如果一開始永久代大小沒有設(shè)置、或者設(shè)置的很小承二,很有可能一開始就執(zhí)行CMS榆鼠,這讓很多同學(xué)表示懷疑,什么都沒做矢洲,就給我來一次CMS的日志。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缩焦,一起剝皮案震驚了整個(gè)濱河市读虏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袁滥,老刑警劉巖盖桥,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異题翻,居然都是意外死亡揩徊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門嵌赠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塑荒,“玉大人,你說我怎么就攤上這事姜挺〕菟埃” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵炊豪,是天一觀的道長凌箕。 經(jīng)常有香客問我,道長词渤,這世上最難降的妖魔是什么牵舱? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮缺虐,結(jié)果婚禮上芜壁,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好沿盅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布把篓。 她就那樣靜靜地躺著,像睡著了一般腰涧。 火紅的嫁衣襯著肌膚如雪韧掩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天窖铡,我揣著相機(jī)與錄音疗锐,去河邊找鬼。 笑死费彼,一個(gè)胖子當(dāng)著我的面吹牛滑臊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箍铲,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼雇卷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颠猴?” 一聲冷哼從身側(cè)響起关划,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翘瓮,沒想到半個(gè)月后贮折,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡资盅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年调榄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呵扛。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡每庆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出今穿,到底是詐尸還是另有隱情扣孟,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布荣赶,位于F島的核電站凤价,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拔创。R本人自食惡果不足惜利诺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剩燥。 院中可真熱鬧慢逾,春花似錦立倍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至君珠,卻和暖如春寝志,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背策添。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工材部, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唯竹。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓乐导,卻偏偏與公主長得像,于是被迫代替她去往敵國和親浸颓。 傳聞我的和親對象是個(gè)殘疾皇子物臂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容