JVM Survivor行為一探究竟

MaxTenuringThreshold:

說到Survivor就不得不提及這個參數(shù),笨神(微信公眾號:"你假笨", 想學(xué)習(xí)JVM調(diào)優(yōu)的話赂鲤,強烈推薦關(guān)注這個公眾號)昨天在JVM分享群里分享了這個參數(shù), 總結(jié)如下:
這個參數(shù)主要作用是設(shè)置在YGC的時候鹏往,新生代的對象正常情況下最多經(jīng)過多少次YGC的過程會晉升到老生代邑时,注意是表示最多而不是一定稻艰,也就是說某個對象的age其實并不是一定要達到這個值才會晉升到Old的诽偷,當(dāng)你設(shè)置這個值的時候客给,第一次會以它為準(zhǔn)用押,后面的就不一定以它為準(zhǔn)了,而是JVM會自動計算在0~15之間決定靶剑,但不會超過這個值蜻拨。如果配置了CMS GC,這個值默認是6桩引;PS的話這個值默認是15缎讼。這個值最大你可以設(shè)置到15,因為jvm里就4個bit來存這個值坑匠,所以最大就是1111血崭,即15;

引申問題

那么JVM是怎么計算接下來S區(qū)的對象晉升到Old區(qū)的age的呢?介紹兩個重要的JVM參數(shù):

-XX:TargetSurvivorRatio

一個計算期望S區(qū)存活大小(Desired survivor size)的參數(shù). 默認參數(shù)為50厘灼,即50%夹纫。可參考JVMPocket设凹。

PrintTenuringDistribution

輸出S區(qū)各個age的對象信息, 用法:-XX:+PrintTenuringDistribution, -XX:-PrintTenuringDistribution
例如, gc日志如下:
new threshold 1 (max 6)
- age 1: 1048608 bytes, 1048608 total
- age 2: 524304 bytes, 1572912 total

當(dāng)一個S區(qū)中各個age的對象的總size大于或等于Desired survivor size ( TargetSurvivorRatio * S0 / 100 )舰讹,則重新計算age,以age和MaxTenuringThreshold兩者的最小值為準(zhǔn)闪朱;驗證這個結(jié)論的Java代碼如下:

public class GcSurvivorTest {

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

        // 這兩個對象不會被回收, 用于在s0和s1不斷來回拷貝增加age直到達到PretenureSizeThreshold晉升到old
        byte[] byte1m_1 = new byte[1 * 512 * 1024];
        byte[] byte1m_2 = new byte[1 * 512 * 1024];

        // YoungGC后, byte1m_1 和 byte1m_2的age為1
        youngGc(1);
        Thread.sleep(3000);

        // 再次YoungGC后, byte1m_1 和 byte1m_2的age為2
        youngGc(1);
        Thread.sleep(3000);

        // 第三次YoungGC后, byte1m_1 和 byte1m_2的age為3
        youngGc(1);
        Thread.sleep(3000);

        // 這次再ygc時, 由于byte1m_1和byte1m_2的年齡已經(jīng)是3月匣,且MaxTenuringThreshold=3, 所以這兩個對象會晉升到Old區(qū)域,且ygc后, s0(from)和s1(to)空間中的對象被清空
        youngGc(1);
        Thread.sleep(3000);

        // main方法中分配的對象不會被回收, 不斷分配是為了達到TargetSurvivorRatio這個比例指定的值, 即5M*60%=3M(Desired survivor size),說明: 5M為S區(qū)的大小奋姿,60%為TargetSurvivorRatio參數(shù)指定锄开,如下三個對象分配后就能夠達到Desired survivor size
        byte[] byte1m_4 = new byte[1 * 1024 * 1024];
        byte[] byte1m_5 = new byte[1 * 1024 * 1024];
        byte[] byte1m_6 = new byte[1 * 1024 * 1024];

        // 這次ygc時, 由于s區(qū)已經(jīng)占用達到了60%(-XX:TargetSurvivorRatio=60), 所以會重新計算對象晉升的age,計算公式為:min(age, MaxTenuringThreshold) = 1
        youngGc(1);
        Thread.sleep(3000);

        // 由于前一次ygc時算出age=1, 所以這一次再ygc時, byte1m_4, byte1m_5, byte1m_6就會晉升到Old區(qū), 而不需要等MaxTenuringThreshold這么多次, 此次ygc后, s0(from)和s1(to)空間中對象再次被清空, 對象全部晉升到old
        youngGc(1);
        Thread.sleep(3000);

        System.out.println("hello world");
    }

    private static void youngGc(int ygcTimes){
        for(int i=0; i<ygcTimes*40; i++) {
            byte[] byte1m = new byte[1 * 1024 * 1024];
        }
    }

}

代碼配套的JVM參數(shù)(Eden: 40M, S0/S1: 5M, Old: 150M):
-verbose:gc -Xmx200M -Xmn50M -XX:TargetSurvivorRatio=60 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=3

由于JVM參數(shù)申明了-verbose:gc, 所以直接可以通過控制臺輸出gc日志信息驗證上面的結(jié)論胀蛮,gc日志如下:

2017-07-22T16:23:48.792+0800: [GC (Allocation Failure) 2017-07-22T16:23:48.792+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   1:    1643904 bytes,    1643904 total
: 40448K->1613K(46080K), 0.0016580 secs] 40448K->1613K(123904K), 0.0029600 secs] [Times: user=0.03 sys=0.00, real=0.00 secs] 
2017-07-22T16:23:51.802+0800: [GC (Allocation Failure) 2017-07-22T16:23:51.802+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   2:    1640840 bytes,    1640840 total
: 42335K->1878K(46080K), 0.0020202 secs] 42335K->1878K(123904K), 0.0020925 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2017-07-22T16:23:54.812+0800: [GC (Allocation Failure) 2017-07-22T16:23:54.812+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
- age   3:    1640536 bytes,    1640536 total
: 41990K->1777K(46080K), 0.0017066 secs] 41990K->1777K(123904K), 0.0017903 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2017-07-22T16:23:57.821+0800: [GC (Allocation Failure) 2017-07-22T16:23:57.821+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
: 42504K->0K(46080K), 0.0056289 secs] 42504K->1651K(123904K), 0.0057150 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
2017-07-22T16:24:00.833+0800: [GC (Allocation Failure) 2017-07-22T16:24:00.833+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 1 (max 3)
- age   1:    3145776 bytes,    3145776 total
: 40731K->3072K(46080K), 0.0023655 secs] 42382K->4723K(123904K), 0.0024508 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2017-07-22T16:24:03.843+0800: [GC (Allocation Failure) 2017-07-22T16:24:03.843+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 3 (max 3)
: 43806K->0K(46080K), 0.0034668 secs] 45457K->4723K(123904K), 0.0035526 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
hello world
Heap
 par new generation   total 46080K, used 15955K [0x00000000f3800000, 0x00000000f6a00000, 0x00000000f6a00000)
  eden space 40960K,  38% used [0x00000000f3800000, 0x00000000f4794e90, 0x00000000f6000000)
  from space 5120K,   0% used [0x00000000f6000000, 0x00000000f6000000, 0x00000000f6500000)
  to   space 5120K,   0% used [0x00000000f6500000, 0x00000000f6500000, 0x00000000f6a00000)
 concurrent mark-sweep generation total 77824K, used 4723K [0x00000000f6a00000, 0x00000000fb600000, 0x0000000100000000)
 Metaspace       used 2840K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 305K, capacity 386K, committed 512K, reserved 1048576K
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末院刁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粪狼,更是在濱河造成了極大的恐慌退腥,老刑警劉巖任岸,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異狡刘,居然都是意外死亡享潜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門嗅蔬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剑按,“玉大人,你說我怎么就攤上這事澜术∫蘸” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵鸟废,是天一觀的道長猜敢。 經(jīng)常有香客問我,道長盒延,這世上最難降的妖魔是什么缩擂? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮添寺,結(jié)果婚禮上胯盯,老公的妹妹穿的比我還像新娘。我一直安慰自己计露,他們只是感情好博脑,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著票罐,像睡著了一般趋厉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胶坠,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音繁堡,去河邊找鬼沈善。 笑死,一個胖子當(dāng)著我的面吹牛椭蹄,可吹牛的內(nèi)容都是我干的闻牡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼绳矩,長吁一口氣:“原來是場噩夢啊……” “哼罩润!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翼馆,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤割以,失蹤者是張志新(化名)和其女友劉穎金度,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體严沥,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡猜极,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了消玄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跟伏。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翩瓜,靈堂內(nèi)的尸體忽然破棺而出受扳,到底是詐尸還是另有隱情,我是刑警寧澤兔跌,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布勘高,位于F島的核電站,受9級特大地震影響浮定,放射性物質(zhì)發(fā)生泄漏相满。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一桦卒、第九天 我趴在偏房一處隱蔽的房頂上張望立美。 院中可真熱鬧,春花似錦方灾、人聲如沸建蹄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洞慎。三九已至,卻和暖如春嘿棘,著一層夾襖步出監(jiān)牢的瞬間劲腿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工鸟妙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留焦人,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓重父,卻偏偏與公主長得像花椭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子房午,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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