[JVM]理解GC日志

1. 輸出GC日志

通過(guò)閱讀GC日志,我們可以了解Java虛擬機(jī)內(nèi)存分配與回收策略论熙。
先來(lái)看一個(gè)簡(jiǎn)單的示例惫东,通過(guò)設(shè)置VM參數(shù)"XX:+PrintGCDetails"就可以打印出GC日志

zhanghuamaodeMacBook-Pro:java zhanghuamao$ java -XX:+PrintGCDetails TestClass
hello
Heap
 PSYoungGen      total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
  eden space 65536K, 6% used [0x000000076ab00000,0x000000076aed7240,0x000000076eb00000)
  from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
  to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
 ParOldGen       total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
  object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)
 Metaspace       used 2630K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 286K, capacity 386K, committed 512K, reserved 1048576K
  • PSYoungGen
    PS是Parallel Scavenge收集器的縮寫(xiě)跟束,它配套的新生代稱(chēng)為PSYoungGen励翼,新生代又分化eden space、from space和to space這三部分

  • ** ParOldGen**
    Parallel Scavenge收集器配套的老年代

  • Metaspace
    Parallel Scavenge收集器配套的永久代

  • total & used
    總的空間和用掉的空間

2. GC日志分析

2.1 新生代Minor GC

先來(lái)回顧下垃圾回收算法,通常新生代按照8:1:1(eden space + survivor from space + survivor to space)進(jìn)行內(nèi)存劃分状土,新生產(chǎn)的對(duì)象會(huì)被放到eden space,當(dāng)eden內(nèi)存不足時(shí)伺糠,就會(huì)將存活對(duì)象移動(dòng)到survivor區(qū)域蒙谓,如果survivor空間也不夠時(shí),就需要從老年代中進(jìn)行分配擔(dān)保训桶,將存活的對(duì)象移動(dòng)老年代累驮,這就是一次Minor GC的過(guò)程。

新生代

1. 示例代碼

  • code
/**
 * VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
 * -XX:SurvivorRatio=8 -XX:+UseSerialGC
 */

public class MinorGCTest {
    private static final int _1MB = 1024 * 1024;

    public static void testAllocation() {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[4 * _1MB];
    }

    public static void main(String[] agrs) {
        testAllocation();
    }
}
  • VM參數(shù)說(shuō)明
Option Description
-verbose:gc 顯示GC的操作內(nèi)容
-Xms20M -Xmx20M 設(shè)置堆大小為20M
-Xmn10M 設(shè)置新生代的內(nèi)存空間大小為10M
-XX:+PrintGCDetails 打印GC中的變化
-XX:SurvivorRatio=8 新生代中Eden區(qū)域與Survivor區(qū)域的大小比值
-XX:+UseSerialGC 在新生代和老年代中使用串行收集器舵揭,由于-verbose:gc參數(shù)對(duì)Parallel Scavenge收集器不起作用谤专,無(wú)法顯示顯示GC的操作內(nèi)容,因此采用串行收集器
  • 示例代碼說(shuō)明
  • 該段代碼一共創(chuàng)建了4個(gè)數(shù)組對(duì)象午绳,在給allocation4分配空間前的內(nèi)存空間使用情況如下:

before MinorGC
  • 需要執(zhí)行一次MinorGC才能給allocation4分配空間置侍,分配成功以后內(nèi)存空間使用情況如下:

after MinorGC

2. GC日志

Minor GC日志
  • [GC [DefNew ... ...]

  • GC日志開(kāi)頭的信息通過(guò)設(shè)置-verbose:gc參數(shù)后才能輸出。

  • "[GC""[Full GC"說(shuō)明這次垃圾收集的停頓類(lèi)型,如果這次GC發(fā)生了Stop-The-World墅垮,則為"[Full GC"惕医,否則為"[GC"

  • "[DefNew "表示GC發(fā)生的區(qū)域?yàn)镾erial收集器的新生代中,DefNew是"Default New Generation"的縮寫(xiě)算色。Serial收集器的老年代和永久代分別表示為"Tenured"抬伺、"Perm"

  • ** eden space 8192K, 52% used**

  • 新生代的Eden區(qū)總共大小為8MB,使用掉的4MB是用來(lái)存放allocation4對(duì)象

  • tenured generation total 10240K, used 6144K

  • 老年代大小為10MB灾梦,使用掉的6MB是用來(lái)存放allocation1峡钓、allocation2和allocation3這3個(gè)對(duì)象

2.2 大對(duì)象直接進(jìn)入老年代

1. 示例代碼

  • code
/**
 * VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
 * -XX:SurvivorRatio=8 -XX:+UseSerialGC      
 * -XX:PretenureSizeThreshold=3145728
 */

public class TestClass2 {
    private static final int _1MB = 1024 * 1024;
    
    public static void testPretenureSizeThreshold() {
        byte[] allocation;
        allocation = new byte[4 * _1MB];
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        testPretenureSizeThreshold();
    }

}
  • VM參數(shù)說(shuō)明
Option Description
-XX:PretenureSizeThreshold=3145728 所占用內(nèi)存大于該值的對(duì)象直接分配到老年代,3145728為3MB
  • 示例代碼說(shuō)明
    該段代碼創(chuàng)建了一個(gè)數(shù)組對(duì)象allocation若河,大小為4MB能岩,已經(jīng)超出PretenureSizeThreshold設(shè)置的范圍,該對(duì)象將直接被分配到老年代中萧福。

2. GC日志

大對(duì)象直接進(jìn)入老年代-GC日志
  • tenured generation total 10240K, used 4096K
    老年代大小為10MB拉鹃,用掉的4MB用來(lái)存放allocation對(duì)象

2.3 長(zhǎng)期存活的對(duì)象進(jìn)入老年代

1. 示例代碼

  • code
/**
 * VM agrs: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
 * -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:MaxTenuringThreshold=1
 */

public class TestClass3 {
    private static final int _1MB = 1024 * 1024;

    public static void testTenuringThreshold() {
        byte[] allocation1, allocation2, allocation3;
        allocation1 = new byte[_1MB / 4];
        allocation2 = new byte[4 * _1MB];
        allocation3 = new byte[4 * _1MB];
        allocation3 = null;
        allocation3 = new byte[4 * _1MB];
    }

    public static void main(String[] agrs) {
        testTenuringThreshold();
    }
}
  • VM參數(shù)說(shuō)明
Option Description
-XX:MaxTenuringThreshold=1 對(duì)象晉升為老年代的年齡閥值為1
  • 示例代碼說(shuō)明
    該段代碼創(chuàng)建了3個(gè)數(shù)組對(duì)象,當(dāng)執(zhí)行到"allocation3 = new byte[4 * _1MB]; "時(shí)鲫忍,Eden已經(jīng)被占用了256KB + 4MB膏燕,而創(chuàng)建allocation3需要4MB,已經(jīng)超過(guò)Eden的大小8MB悟民,需要先發(fā)生一次MinorGC坝辫,才能保證有空間存放allocation3

2. GC日志

  • 設(shè)置參數(shù)為MaxTenuringThreshold=1的運(yùn)行結(jié)果

  • 由GC日志開(kāi)頭的兩句"[GC [DefNew"可知,該段代碼一共發(fā)生了2次GC射亏,第一次是"allocation3 = new byte[4 * _1MB]; "近忙,第二次是執(zhí)行allocation3 = null時(shí)

  • allocation1在經(jīng)過(guò)第一次GC時(shí),對(duì)象年齡變成了1智润,由于設(shè)置的MaxTenuringThreshold=1及舍,當(dāng)發(fā)生第二次GC時(shí),allocation1的年齡已經(jīng)超出了設(shè)置的閥值窟绷,allocation1進(jìn)入到老年代击纬,因此,新生代的from space使用空間為0钾麸,對(duì)應(yīng)GC語(yǔ)句為from space 1024K, 0% used

MaxTenuringThreshold=1
  • 設(shè)置參數(shù)為MaxTenuringThreshold=15的運(yùn)行結(jié)果
    由于設(shè)置的MaxTenuringThreshold=15更振,發(fā)生第二次GC時(shí),allocation1的年齡沒(méi)有超出設(shè)置的閥值饭尝,因此肯腕,新生代的from space使用空間不為0,對(duì)應(yīng)GC語(yǔ)句為from space 1024K, 44% used

MaxTenuringThreshold=15

3. 參考

  • 深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐(第2版)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钥平,一起剝皮案震驚了整個(gè)濱河市实撒,隨后出現(xiàn)的幾起案子姊途,更是在濱河造成了極大的恐慌,老刑警劉巖知态,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捷兰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡负敏,警方通過(guò)查閱死者的電腦和手機(jī)贡茅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)其做,“玉大人顶考,你說(shuō)我怎么就攤上這事⊙梗” “怎么了驹沿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蹈胡。 經(jīng)常有香客問(wèn)我渊季,道長(zhǎng),這世上最難降的妖魔是什么罚渐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任却汉,我火速辦了婚禮,結(jié)果婚禮上搅轿,老公的妹妹穿的比我還像新娘。我一直安慰自己富玷,他們只是感情好璧坟,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著赎懦,像睡著了一般雀鹃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上励两,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天黎茎,我揣著相機(jī)與錄音,去河邊找鬼当悔。 笑死傅瞻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盲憎。 我是一名探鬼主播嗅骄,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼饼疙!你這毒婦竟也來(lái)了溺森?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屏积,沒(méi)想到半個(gè)月后医窿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炊林,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年姥卢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铛铁。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隔显,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饵逐,到底是詐尸還是另有隱情括眠,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布倍权,位于F島的核電站掷豺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏薄声。R本人自食惡果不足惜当船,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望默辨。 院中可真熱鬧德频,春花似錦、人聲如沸缩幸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)表谊。三九已至钞护,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爆办,已是汗流浹背难咕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留距辆,地道東北人余佃。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像跨算,于是被迫代替她去往敵國(guó)和親咙冗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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

  • 原文閱讀 前言 這段時(shí)間懈怠了漂彤,罪過(guò)雾消! 最近看到有同事也開(kāi)始用上了微信公眾號(hào)寫(xiě)博客了灾搏,挺好的~給他們點(diǎn)贊,這博客我...
    碼農(nóng)戲碼閱讀 5,994評(píng)論 2 31
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前立润,它的class會(huì)被類(lèi)裝載器裝入方法區(qū)(Permanent區(qū))狂窑,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,673評(píng)論 0 7
  • Java技術(shù)體系中所提倡的自動(dòng)內(nèi)存管理最終可以歸結(jié)為自動(dòng)化地解決了兩個(gè)問(wèn)題:給對(duì)象分配內(nèi)存以及回收分配給對(duì)象的內(nèi)存...
    夢(mèng)工廠閱讀 4,658評(píng)論 4 12
  • 1.一些概念 1.1.數(shù)據(jù)類(lèi)型 Java虛擬機(jī)中,數(shù)據(jù)類(lèi)型可以分為兩類(lèi):基本類(lèi)型和引用類(lèi)型桑腮∪基本類(lèi)型的變量保存原始...
    落落落落大大方方閱讀 4,545評(píng)論 4 86
  • 參數(shù)設(shè)置 在Java虛擬機(jī)的參數(shù)中,有3種表示方法用“ps -ef |grep "java"命令破讨,可以得到當(dāng)前Ja...
    九問(wèn)閱讀 9,155評(píng)論 2 52