垃圾收集器與故障處理工具

這篇文章記錄的是:深入理解java虛擬機(jī)(第二版)第三章與第四章的內(nèi)容

1. GC要做的三件事:

Q1: 哪些內(nèi)存需要回收蛾号?
GC回收的一般是堆(只用在程序運(yùn)行期間才能知道會(huì)創(chuàng)建哪些對(duì)象)和方法區(qū)(一個(gè)方法中的多個(gè)分支需要的內(nèi)存可能不一樣)中存放的已“死去的”java對(duì)象喊儡,那怎么判斷對(duì)象已經(jīng)“死去”了呢翎卓?1. 引用計(jì)數(shù)算法:給對(duì)象添加一個(gè)計(jì)數(shù)器诗充,每當(dāng)在一個(gè)地方引用它時(shí)镊掖,計(jì)數(shù)器就加1缎除,當(dāng)引用失效時(shí)膝但,計(jì)數(shù)器就減1环形,任何時(shí)候計(jì)數(shù)器為零的對(duì)象是不可能再被使用的策泣。問(wèn)題:很難解決對(duì)象之間相互循環(huán)引用的問(wèn)題。2. 可達(dá)性分析算法:以一系列被稱(chēng)為“GC Roots”的對(duì)象作為起始點(diǎn)抬吟,從這個(gè)節(jié)點(diǎn)開(kāi)始向下搜索萨咕,搜索所走過(guò)的路徑稱(chēng)為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何的引用鏈相連火本,則證明此對(duì)象不可用危队,即可回收。在Java中钙畔,可作為GC Roots的對(duì)象包括:虛擬機(jī)棧中引用的對(duì)象茫陆、方法區(qū)中類(lèi)靜態(tài)屬性引用的對(duì)象、方法區(qū)中常量引用的對(duì)象擎析、本地方法棧中JNI引用的對(duì)象
Q2:什么時(shí)候回收簿盅?
系統(tǒng)決定,無(wú)法預(yù)測(cè)
Q3:如何回收揍魂?
對(duì)于不同的內(nèi)存采用不同的收集算法桨醋。比如:Java一般把堆分為新生代和老年代,新生代(特點(diǎn):朝生夕死)一般采用復(fù)制算法现斋,老年代(特點(diǎn):存活率高)采用“標(biāo)記-清除”或者“標(biāo)記-整理”

2. 垃圾收集算法

2.1 標(biāo)記-清除算法

如同它的名字一樣喜最,算法分為“標(biāo)記”和“清除兩個(gè)階段”:首先標(biāo)記出所有要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象步责。不足:1. 標(biāo)記和清除兩個(gè)過(guò)程的效率都不高返顺。2. 標(biāo)記清除之后會(huì)產(chǎn)生許多大量不連續(xù)的內(nèi)存碎片禀苦,空間碎片太多可能導(dǎo)致以后在程序運(yùn)行過(guò)程中需要分配較大的對(duì)象時(shí),無(wú)法找到足夠連續(xù)的內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作遂鹊。

2.2 復(fù)制算法

將可用內(nèi)存按容量劃分為大小相等的兩塊振乏,每次只使用其中一塊,當(dāng)這一塊的內(nèi)存用完了秉扑,就將還存活著的對(duì)象復(fù)制到另一塊上面慧邮,然后把使用過(guò)的內(nèi)存空間一次清理掉。不足:內(nèi)存縮小為原來(lái)的一般舟陆。
根據(jù)IBM公司研究表明:98%的對(duì)象都是“朝生夕死”的误澳,所以?xún)?nèi)存劃分為一塊較大的Eden和兩塊較小的Survivor,比率:8:1:1秦躯,每次使用Eden和其中一塊Survivor忆谓。當(dāng)垃圾回收時(shí),將Eden和Survivor中還存活的對(duì)象一次性復(fù)制到另一塊Survivor空間上踱承,最后清理掉Eden和剛才用過(guò)的Survivor空間倡缠,當(dāng)然,我們不能保證每次回收時(shí)只有不多于10%的對(duì)象存活茎活,當(dāng)Survivor空間不夠用時(shí)昙沦,進(jìn)行分配擔(dān)保。

2.3 標(biāo)記-整理算法

復(fù)制算法在對(duì)象存活率較高的時(shí)候就要就行較多的復(fù)制操作载荔,效率將會(huì)變低盾饮。標(biāo)記-整理算法與“標(biāo)記-清除”算法一樣,但是后續(xù)步驟并不是直接對(duì)可回收的對(duì)象進(jìn)行清理懒熙,而是讓所有存活的對(duì)象都像一端移動(dòng)丘损,然后直接清理掉邊界以外的內(nèi)存。

2. 垃圾收集器

2.1 Serial 收集器

單線程的收集器煌珊。單線程的意義并不僅僅說(shuō)明它只會(huì)是有一個(gè)CPU或一條收集線程去完成垃圾收集的工作号俐,更重要的是在它進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程(Stop The World)定庵,直到它收集結(jié)束吏饿。很明顯,“Stop The World” 使得用戶體驗(yàn)度不好蔬浙。


image.png
  • 使用場(chǎng)景:是HotSpot在Client模式下默認(rèn)的新生代收集器

2.2 ParNew收集器

ParNew收集器是Serial收集器的多線程版本猪落,除了使用多線程進(jìn)行垃圾收集之外,其他的控制參數(shù)與Serial收集器幾乎完全一樣畴博。


image.png
  • 使用場(chǎng)景:在Server模式下笨忌,ParNew收集器是一個(gè)非常重要的收集器,因?yàn)槌齋erial外俱病,目前只有它能與CMS收集器配合工作(因?yàn)镻arallel Scavenge(以及G1)都沒(méi)有使用傳統(tǒng)的GC收集器代碼框架官疲,而另外獨(dú)立實(shí)現(xiàn))袱结,但在單個(gè)CPU環(huán)境中,不會(huì)比Serail收集器有更好的效果途凫,因?yàn)榇嬖诰€程交互開(kāi)銷(xiāo)垢夹。

2.3 Parallel Scavenge 收集器

使用復(fù)制算法的收集器,也是并行的多線程收集器维费。特點(diǎn):達(dá)到一個(gè)可控制的吞吐量果元,所謂吞吐量就是CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值,即吞吐量=運(yùn)行用戶代碼/(運(yùn)行用戶代碼+垃圾收集時(shí)間)犀盟。該收集器提供了兩個(gè)參數(shù)用于精確地控制吞吐量而晒,分別是控制垃圾收集停頓時(shí)間的-XX:MaxGCPauseMillis參數(shù)以及直接設(shè)置吞吐量大小的-XX:GCTimeRatio參數(shù)。不過(guò)阅畴,不要認(rèn)為把停頓時(shí)間設(shè)置小一點(diǎn)就能使系統(tǒng)的垃圾收集速度變得更快倡怎,GC停頓時(shí)間縮短是以犧牲吞吐量和新生代空間來(lái)?yè)Q取的:系統(tǒng)把新生代調(diào)小一些,收集300MB新生代肯定比收集500MB快吧贱枣,這也直接導(dǎo)致垃圾收集發(fā)生得更加頻繁诈胜,原來(lái)10秒收集一次,每次停頓10毫秒冯事,現(xiàn)在變成5秒收集一次、每次停頓70毫秒血公。停頓時(shí)間的確在下降昵仅,但吞吐量也降下來(lái)了。

  • 使用場(chǎng)景:高吞吐量為目標(biāo)累魔,即減少垃圾收集時(shí)間摔笤,讓用戶代碼獲得更長(zhǎng)的運(yùn)行時(shí)間; 當(dāng)應(yīng)用程序運(yùn)行在具有多個(gè)CPU上垦写,對(duì)暫停時(shí)間沒(méi)有特別高的要求時(shí)吕世,即程序主要在后臺(tái)進(jìn)行計(jì)算,而不需要與用戶進(jìn)行太多交互梯投;


    image.png

2.4 Serial Old 收集器

Serial Old是Serial收集器的老年代版本命辖,它是使用“標(biāo)記-整理”算法的單線程收集器。這個(gè)收集器的主要意義在于給Client模式下的虛擬機(jī)使用分蓖。如果在Server模式下尔艇,主要有兩大用途:1. JDK1.5之前的版本中與Parallel Scavenge收集器搭配使用。2. 作為CMS收集器的后備預(yù)案么鹤。


image.png
  • 使用場(chǎng)景:主要用于Client模式终娃;Server模式:作為CMS收集器的后備預(yù)案

2.5 Parallel Old 收集器

Parallel Old 是Parallel Scavenge 收集器的老年代版本,使用多線程和“標(biāo)記-整理”算法蒸甜。在JDK1.6之前棠耕,Parallel Scavenge收集器余佛,老年代除了Serial Old之外別無(wú)選擇,由于Serial Old 收集器在性能上的“拖累”窍荧,使得Parallel Scavenge 收集器未必能獲得吞吐量最大化的效果辉巡。知道Parallel Old 收集器出現(xiàn)之后,“吞吐量?jī)?yōu)先”才有了名副其實(shí)的組合搅荞。


image.png
  • 使用場(chǎng)景:JDK1.6及之后红氯,在Server模式,多CPU的情況下用來(lái)代替老年代的Serial Old收集器咕痛;

2.5 CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器痢甘。采用“標(biāo)記-清除”算法,總共有4個(gè)步驟:

  1. 初始標(biāo)記
  2. 并發(fā)標(biāo)記
  3. 重新標(biāo)記
  4. 并發(fā)清除
    初始標(biāo)記和重新標(biāo)記需要“Stop The Word”茉贡。初始標(biāo)記僅僅只是標(biāo)記GC Root能直接關(guān)聯(lián)的對(duì)象塞栅,速度很快,并發(fā)標(biāo)記階段進(jìn)行GC Roots Tracing過(guò)程腔丧,而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那部分對(duì)象的標(biāo)記記錄放椰。優(yōu)點(diǎn):并發(fā)收集、低停頓愉粤。缺點(diǎn):1. CMS收集器對(duì)CPU資源非常敏感(占用CPU砾医,導(dǎo)致應(yīng)用程序變慢,總吞吐量降低)衣厘。2. CMS收集器無(wú)法處理浮動(dòng)垃圾(清理的同時(shí)如蚜,程序還在連續(xù)不斷的產(chǎn)生新的垃圾)。3. “標(biāo)記-清除”算法會(huì)產(chǎn)生大量的空間碎片影暴。


    image.png
  • 使用場(chǎng)景: 與用戶交互較多的場(chǎng)景错邦,希望系統(tǒng)停頓時(shí)間最短,注重服務(wù)的響應(yīng)速度型宙,以給用戶帶來(lái)較好的體驗(yàn)撬呢, 如常見(jiàn)WEB、B/S系統(tǒng)的服務(wù)器上的應(yīng)用

2.6 G1 收集器

G1(Garbage-First)收集器
G1收集器是當(dāng)今收集器技術(shù)的最前沿成果之一妆兑。用來(lái)替換JDK1.5中發(fā)布的CMS收集器魂拦。特點(diǎn):

  1. 并行與并發(fā):充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢(shì)搁嗓。
  2. 分代收集:G1不需要配合其他的收集器就能獨(dú)立管理整個(gè)GC堆晨另,但它會(huì)采用不同的方式去處理新創(chuàng)建的對(duì)象和已經(jīng)存活了一段時(shí)間、熬過(guò)多次GC的舊對(duì)象谱姓。
  3. 空間整合:與CMS的“標(biāo)記-清除”算法不同借尿,G1是基于“標(biāo)記-整理”算法實(shí)現(xiàn)的,所以不會(huì)產(chǎn)生空間碎片。
  4. 可預(yù)測(cè)停頓:能指定在一個(gè)長(zhǎng)度為M毫秒的時(shí)間片段內(nèi)路翻,消耗在垃圾收集上的時(shí)間不得超過(guò)N毫秒狈癞。
    G1收集器大致分為以下幾步:
  5. 初始標(biāo)記
  6. 并發(fā)標(biāo)記
  7. 最終標(biāo)記
  8. 篩選回收
    可以看出來(lái),過(guò)程與CMS差不多茂契,最終標(biāo)記階段會(huì)把Remembered Set Logs的數(shù)據(jù)合并到Remembered Set中蝶桶。最后在篩選回收階段首先對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序,根據(jù)用戶所期望的GC停頓時(shí)間來(lái)制定回收計(jì)劃


    image.png
  • 使用場(chǎng)景: 面向服務(wù)端應(yīng)用掉冶,針對(duì)具有大內(nèi)存真竖、多處理器的機(jī)器,最主要的應(yīng)用是為需要低GC延遲厌小,并具有大堆的應(yīng)用程序提供解決方案恢共;


    image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市璧亚,隨后出現(xiàn)的幾起案子讨韭,更是在濱河造成了極大的恐慌,老刑警劉巖癣蟋,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件透硝,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡疯搅,警方通過(guò)查閱死者的電腦和手機(jī)濒生,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)幔欧,“玉大人甜攀,你說(shuō)我怎么就攤上這事∷龉荩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵恒序,是天一觀的道長(zhǎng)瘦麸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)歧胁,這世上最難降的妖魔是什么滋饲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮喊巍,結(jié)果婚禮上屠缭,老公的妹妹穿的比我還像新娘。我一直安慰自己崭参,他們只是感情好呵曹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般奄喂。 火紅的嫁衣襯著肌膚如雪铐殃。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,084評(píng)論 1 291
  • 那天跨新,我揣著相機(jī)與錄音富腊,去河邊找鬼。 笑死域帐,一個(gè)胖子當(dāng)著我的面吹牛赘被,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肖揣,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼民假,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了许饿?” 一聲冷哼從身側(cè)響起阳欲,我...
    開(kāi)封第一講書(shū)人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陋率,沒(méi)想到半個(gè)月后球化,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓦糟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年筒愚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菩浙。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡巢掺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劲蜻,到底是詐尸還是另有隱情陆淀,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布先嬉,位于F島的核電站轧苫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疫蔓。R本人自食惡果不足惜含懊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衅胀。 院中可真熱鬧岔乔,春花似錦、人聲如沸滚躯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至剿配,卻和暖如春搅幅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呼胚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工茄唐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝇更。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓沪编,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親年扩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚁廓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351