Java垃圾回收(3)
這是我之前的兩個(gè)垃圾收集博客文章中的內(nèi)容:
并發(fā)標(biāo)記掃描
Hotspot中的并行垃圾收集器旨在最大程度地減少應(yīng)用程序進(jìn)行垃圾收集所花費(fèi)的時(shí)間,這稱為吞吐量 。 對(duì)于所有應(yīng)用程序來說,這并不是一個(gè)適當(dāng)?shù)臋?quán)衡取舍–有些應(yīng)用程序還要求個(gè)別的暫停時(shí)間要短一些,這被稱為延遲要求。
并行標(biāo)記掃描 (CMS)收集器被設(shè)計(jì)為比并行收集器低的延遲收集器。 該設(shè)計(jì)的關(guān)鍵部分是嘗試在應(yīng)用程序運(yùn)行的同時(shí)進(jìn)行部分垃圾回收。 這意味著當(dāng)收集器需要暫停應(yīng)用程序的執(zhí)行時(shí),它不需要暫停那么長時(shí)間。
在這一點(diǎn)上,您可能會(huì)想: “并行和并發(fā)意味著不是很相似嗎?” 在GC的上下文中, 并行意味著“使用多個(gè)線程同時(shí)執(zhí)行G??C”,而并行意味著“ GC與應(yīng)用程序在其收集的同時(shí)運(yùn)行”。
年輕的世代收藏
CMS中的年輕發(fā)電器收集器稱為ParNew ,它實(shí)際上使用了與我之前介紹的并行收集器中的Parallel Scavenge收集器相同的基本算法。
盡管在熱點(diǎn)代碼庫方面,這與Parallel Scavenge還是一個(gè)不同的收集器,因?yàn)樗枰c其他CMS交織其執(zhí)行,并且還為Parallel Scavenge實(shí)現(xiàn)了一個(gè)不同的內(nèi)部API。 Parallel Scavenge會(huì)假設(shè)與哪個(gè)永久性收集器一起使用-特別是ParOld和SerialOld。 赤裸裸地記住,這也意味著年輕的一代收藏家正在制止這個(gè)世界。
終身收藏
與ParOld收集器一樣,CMS終身收集器使用標(biāo)記和清除算法,其中標(biāo)記活動(dòng)對(duì)象,然后刪除無效對(duì)象。 當(dāng)涉及到內(nèi)存管理時(shí),刪除確實(shí)是一個(gè)奇怪的名詞。 收集器實(shí)際上不是在消隱內(nèi)存的意義上刪除對(duì)象,它只是將與該對(duì)象關(guān)聯(lián)的內(nèi)存返回到內(nèi)存系統(tǒng)可以從中分配的空間–空閑列表。 盡管它被稱為并發(fā)標(biāo)記和清除收集器,但并非所有階段都與應(yīng)用程序的執(zhí)行同時(shí)運(yùn)行,其中兩個(gè)階段停止運(yùn)行,四個(gè)階段同時(shí)運(yùn)行。
GC是如何觸發(fā)的?
在ParOld中,當(dāng)永久性堆中的空間不足時(shí),將觸發(fā)垃圾回收。 這種方法行之有效,因?yàn)镻arOld只是暫停了應(yīng)用程序的收集。 為了使應(yīng)用程序在保管期收集期間繼續(xù)運(yùn)行,CMS收集器需要在保管期剩下足夠的工作空間時(shí)開始收集。
因此,CMS將根據(jù)使用期限的長短來啟動(dòng)–想法是,剩余的可用空間是運(yùn)行GC的機(jī)會(huì)之窗。 這稱為啟動(dòng)占用率 ,用堆的滿度來描述,因此0.7的百分比為您提供了30%的堆窗口,以便在堆用完之前運(yùn)行CMS GC。
相數(shù)
觸發(fā)GC后,CMS算法將包含一系列按順序運(yùn)行的階段。
從理論上講,在預(yù)清理階段標(biāo)記的對(duì)象將在下一個(gè)階段-注釋-進(jìn)行查看,但是注釋階段是使世界停滯不前,因此存在預(yù)清理階段,通過同時(shí)執(zhí)行部分注釋工作來嘗試減少注釋暫停。 CMS最初添加到HotSpot時(shí),此階段根本不存在。 它是在Java 1.5中添加的,目的是解決年輕一代的垃圾回收導(dǎo)致暫停并在其后立即加上備注的情況。 這句話還會(huì)引起停頓,這會(huì)造成更痛苦的停頓。 這就是為什么評(píng)論由伊甸園的占用閾值觸發(fā)的原因-目標(biāo)是在年輕的發(fā)電機(jī)停頓之間安排評(píng)論階段的中間時(shí)間。
備注階段也處于暫停狀態(tài),而預(yù)清潔沒有暫停,這意味著進(jìn)行預(yù)清潔會(huì)減少在GC中暫停所花費(fèi)的時(shí)間。
并發(fā)模式故障
有時(shí)CMS無法滿足應(yīng)用程序的需求,因此需要運(yùn)行世界各地的Full GC。 這稱為并發(fā)模式故障,通常會(huì)導(dǎo)致長時(shí)間的暫停。 當(dāng)保有期中沒有足夠的空間來提升對(duì)象時(shí),就會(huì)發(fā)生并發(fā)模式失敗。 造成這種情況的原因有兩個(gè):
- 提升的對(duì)象太大而無法放入內(nèi)存中的任何連續(xù)空間。
- 保有權(quán)使用的空間不足以說明要升級(jí)的活動(dòng)對(duì)象的比率。
之所以會(huì)發(fā)生這種情況,是因?yàn)樵诮o定對(duì)象提升速率的情況下,并發(fā)集合無法足夠快地釋放空間,或者由于CMS收集器的繼續(xù)使用導(dǎo)致了碎片化的堆,并且沒有足夠大的單個(gè)空間來將對(duì)象提升為對(duì)象。 為了正確“整理”使用年限的堆空間,需要完整的GC。
彼爾姆根
CMS默認(rèn)情況下不收集permgen空間,并且需要啟用?XX:+CMSClassUnloadingEnabled標(biāo)志才能這樣做。 如果在使用CMS時(shí),如果未打開此標(biāo)志就用完了permgen空間,它將觸發(fā)Full GC。 而且,permgen空間可以通過類加載器之類的東西將引用保存到普通堆中,這意味著在收集Permgen之前,您可能會(huì)泄漏常規(guī)堆中的內(nèi)存。 在Java 7中,來自類文件的字符串常量也分配在常規(guī)堆中,而不是分配在permgen上,這減少了permgen的消耗,但同時(shí)也增加了來自permgen進(jìn)入常規(guī)堆的對(duì)象引用集。
浮動(dòng)垃圾
在CMS收集結(jié)束時(shí),可能會(huì)刪除某些對(duì)象(稱為浮動(dòng)垃圾)。 從初始標(biāo)記開始取消引用對(duì)象時(shí),就會(huì)發(fā)生這種情況。 并發(fā)的預(yù)清理和備注階段可通過查看已創(chuàng)建,變異或升級(jí)的對(duì)象來確保對(duì)所有活動(dòng)對(duì)象進(jìn)行標(biāo)記。 如果某個(gè)對(duì)象在初始標(biāo)記和標(biāo)記階段之間已被取消引用,則它將需要整個(gè)對(duì)象圖的完整回溯才能找到所有死對(duì)象。 這顯然是非常昂貴的,并且備注階段必須暫停,因?yàn)樗菚和kA段。
對(duì)于CMS用戶而言,這不一定是一個(gè)問題,因?yàn)橄乱淮芜\(yùn)行CMS收集器將清除此垃圾。
摘要
并發(fā)標(biāo)記和掃描通過在應(yīng)用程序運(yùn)行的同時(shí)執(zhí)行某些GC工作,減少了在并行收集器中觀察到的暫停時(shí)間。 它不能完全消除暫停,因?yàn)槠渌惴ǖ囊徊糠中枰獣和?yīng)用程序才能執(zhí)行。
我花了比我原本希望寫這篇博客文章更長的時(shí)間-但是,如果您想知道我的下一篇文章何時(shí)發(fā)布,只需在此博客的右上角輸入您的電子郵件即可通過電子郵件訂閱。
翻譯自: https://www.javacodegeeks.com/2013/06/garbage-collection-in-java-3.html
總結(jié)
以上是生活随笔為你收集整理的Java垃圾回收(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 顺风车路线设置技巧(顺风车设置顺路程度)
- 下一篇: 笛卡尔的天赋观念说(笛卡儿的天赋观念)