久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java中的垃圾回收原理

 orion360doc 2013-06-20

Java中的垃圾回收原理

分類(lèi): java 446人閱讀 評(píng)論(2) 收藏 舉報(bào)

目錄(?)[+]

垃圾回收簡(jiǎn)介

用戶程序(mutator)會(huì)修改還堆區(qū)中的對(duì)象集合,,從存儲(chǔ)管理器處獲取空間,,創(chuàng)建對(duì)象,還可一引入和消除對(duì)已有對(duì)象的引用,。

當(dāng)mutator不能“達(dá)到”某些對(duì)象的時(shí)候,,這些對(duì)象就成了垃圾。

目的:找到不可達(dá)的對(duì)象,,并將這些對(duì)象交給跟蹤空閑空間的存儲(chǔ)管理器,,收回他們所占的資源。


一些基本概念

類(lèi)型安全:任何數(shù)據(jù)分量的類(lèi)型都是可確定的,。

可以在編譯時(shí)刻確定數(shù)據(jù)的類(lèi)型稱(chēng)為靜態(tài)類(lèi)型安全,,運(yùn)行時(shí)刻確定稱(chēng)為動(dòng)態(tài)類(lèi)型。

類(lèi)型不安拳的語(yǔ)言不適合使用自動(dòng)垃圾回收,。

在java中,,除了整型和引用這樣的基本類(lèi)型,所有對(duì)象都被分配在堆區(qū)而不是棧區(qū),。這種設(shè)計(jì)使得程序員不需要關(guān)注變量的生命周期,,但代價(jià)是產(chǎn)生更多的垃圾。


可達(dá)性

對(duì)任何指針解引用就可以被程序直接訪問(wèn)的數(shù)據(jù)則為可達(dá)的,。


局部性原理

        如果一個(gè)程序方位的存儲(chǔ)位置很可能將在一個(gè)很短的時(shí)間段再次被訪問(wèn),,則稱(chēng)這個(gè)程序具有時(shí)間局部性(Temporal locality)。如果被訪問(wèn)過(guò)的存儲(chǔ)位置的臨近位置很可能在一個(gè)很短的時(shí)間段內(nèi)被訪問(wèn),,則該程序具有空間局部性,。

        通常認(rèn)為程序把90%的時(shí)間來(lái)執(zhí)行10%的代碼。


幾種垃圾回收器的原理

標(biāo)記-清除收集器

這種收集器首先遍歷對(duì)象圖并標(biāo)記可到達(dá)的對(duì)象,,然后掃描堆棧以尋找未標(biāo)記對(duì)象并釋放它們的內(nèi)存,。這種收集器一般使用單線程工作并停止其他操作。并且,,由于它只是清除了那些未標(biāo)記的對(duì)象,,而并沒(méi)有對(duì)標(biāo)記對(duì)象進(jìn)行壓縮,導(dǎo)致會(huì)產(chǎn)生大量?jī)?nèi)存碎片,,從而浪費(fèi)內(nèi)存,。

標(biāo)記-壓縮收集器

有時(shí)也叫標(biāo)記-清除-壓縮收集器,,與標(biāo)記-清除收集器有相同的標(biāo)記階段。在第二階段,,則把標(biāo)記對(duì)象復(fù)制到堆棧的新域中以便壓縮堆棧,。這種收集器也停止其他操作。

復(fù)制收集器

這種收集器將堆棧分為兩個(gè)域,,常稱(chēng)為半空間,。每次僅使用一半的空間,JVM生成的新對(duì)象則放在另一半空間中,。GC運(yùn)行時(shí),,它把可到達(dá)對(duì)象復(fù)制到另一半空間,從而壓縮了堆棧,。這種方法適用于短生存期的對(duì)象,,持續(xù)復(fù)制長(zhǎng)生存期的對(duì)象則導(dǎo)致效率降低。并且對(duì)于指定大小堆來(lái)說(shuō),,需要兩倍大小的內(nèi)存,,因?yàn)槿魏螘r(shí)候都只使用其中的一半。

增量收集器

增量收集器把堆棧分為多個(gè)域,,每次僅從一個(gè)域收集垃圾,,也可理解為把堆棧分成一小塊一小塊,每次僅對(duì)某一個(gè)塊進(jìn)行垃圾收集,。這會(huì)造成較小的應(yīng)用程序中斷時(shí)間,,使得用戶一般不能覺(jué)察到垃圾收集器正在工作。


部分回收原理

通常80%~90%的新分配對(duì)象在幾百萬(wàn)條指令之內(nèi)或者再分配了,。

分代收集器(Generational garbage coolection)

 它是基于拷貝回收器和部分回收原理,。

充分利用大多數(shù)對(duì)象“英年早逝”的特性的有效方法。

將堆區(qū)分成一系列小的區(qū)域,,用0,1,2......n對(duì)它們進(jìn)行編號(hào),,序號(hào)越小的區(qū)域存放的對(duì)象越年輕,對(duì)象首先在0區(qū)域被創(chuàng)建,,填滿后垃圾被回收,,可達(dá)對(duì)象被移到1區(qū),每一輪垃圾回收都是針對(duì)序號(hào)小于等于i的區(qū)域進(jìn)行的,,i為當(dāng)前被填滿區(qū)域的最高編號(hào),。


只要對(duì)i進(jìn)行回收,所有序號(hào)小雨i的區(qū)域也將要進(jìn)行垃圾回收,,應(yīng)為較年輕的世代往往包含了較多的垃圾,,也就是更頻繁的被回收。

最老的世代保存了最成熟的對(duì)象,對(duì)這些對(duì)象的回收是最昂貴的,,相當(dāng)于一次完整的回收,??梢疠^長(zhǎng)時(shí)間的停頓,。解決方法是使用列車(chē)算法。


Garbage Collectors in the J2SE 5.0 HotSpot JVM

垃圾回收器的職責(zé)有1)分配內(nèi)存,;2)確保引用的內(nèi)存在內(nèi)存中,;3)回收內(nèi)存中不可達(dá)的對(duì)象。

制定垃圾回收算法的時(shí)候需要做出一些權(quán)衡和選擇:1)串行還是并行,;2)并發(fā)還是stop-the-world,;3)內(nèi)存緊致還是不緊致還是采用拷貝算法。

J2SE 5.0 HotSpot JVM中的四種GC采用的是世代收集器的原理,,如下:



    hotspot(j2se 5.0,按白皮書(shū)上的說(shuō)法也適用于6.0)使用的是所謂的Generational Collection機(jī)制,也就是把對(duì)象分為young和old(還有一種是permanent),young對(duì)象經(jīng)過(guò)幾次回收后(存活較長(zhǎng)時(shí)間后),就會(huì)成為old對(duì)象.之所以采用這種機(jī)制,是基于以下觀察:大部分新建對(duì)象的引用不會(huì)持續(xù)太久,也就說(shuō)是會(huì)die young;少部分的引用會(huì)持續(xù)下來(lái).
    因此,young generation 進(jìn)行Collection會(huì)更多,因此使用的算法對(duì)時(shí)間效率的要求高.而old generation 保存的數(shù)據(jù)較多,使用的算法對(duì)空間的要求效率相對(duì)而言要求就較高了.把對(duì)象分為不同的generation,便于采用不同的算法進(jìn)行操作.
對(duì)應(yīng)的,可以把HotSpotJVM 的內(nèi)存分為:young generation ,oldgeneration ,permanent generation.在這里默認(rèn)首先把對(duì)像都放到區(qū)域的左邊.

J2SEHotSpot JVM 的 4中垃圾回收器都是屬于generational collection.
一般說(shuō)來(lái),新建對(duì)象時(shí)一般都是在young里面分配內(nèi)存,old里面儲(chǔ)存的是young中經(jīng)過(guò)幾次回收依然存活的對(duì)象以及一些一開(kāi)始就在old中分配的大對(duì)象.而permanent generation里面保存的是類(lèi)信息和元數(shù)據(jù).
younggeneration分為一個(gè)Eden區(qū)域和兩個(gè)survivor 區(qū)域.對(duì)象在Eden區(qū)域生成,經(jīng)過(guò)一次GC后存活下來(lái)的對(duì)象進(jìn)入survivor中,并在此經(jīng)過(guò)更嚴(yán)格的考驗(yàn),然后進(jìn)入old .同一時(shí)間只有一個(gè)survivor區(qū)域保存對(duì)象,另一個(gè)為空.

當(dāng)young區(qū)域滿了后,就會(huì)執(zhí)行young區(qū)域的GC算法.當(dāng)old和permanent區(qū)域滿了后,會(huì)先執(zhí)行young的GC.再執(zhí)行old和permanent的GC,如果old區(qū)域?qū)ο筮^(guò)多無(wú)法執(zhí)行young的GC,那么在young區(qū)域執(zhí)行old的GC算法(因?yàn)閮?nèi)存空間耗費(fèi)較少),但是CMS回收器的old算法不行,下面會(huì)說(shuō)明原因.

對(duì)于多線程的應(yīng)用.JVM 使用一個(gè)Thread-LocalAllocation Buffers ,為每個(gè)線程分配一個(gè)區(qū)域來(lái)分配對(duì)象,以排除線程競(jìng)爭(zhēng).如果此區(qū)域滿了的話就使用鎖.

HotSpot的四種GC 回收器:
串行化回收serial collector:
特點(diǎn):回收時(shí)會(huì)暫停應(yīng)用.
young區(qū)域:將Eden和某個(gè)Survivor區(qū)域中的存活的對(duì)象復(fù)制到另一個(gè)Survivor區(qū)域(設(shè)為T(mén)O)(大對(duì)象直接放到old區(qū)域).如果TO區(qū)域滿了,則直接復(fù)制到old區(qū)域.
old區(qū)域:使用mark-sweep-compact GC算法,也就是先標(biāo)記存活對(duì)象,然后清除廢棄對(duì)象,然后把存活對(duì)象都移到一塊區(qū)域,空出一片較大的空閑空間.
適用范圍:大部分客戶端的應(yīng)用都可以使用這種回收算法,這也是HotSpot默認(rèn)的回收算法.在現(xiàn)在的機(jī)器(06年)上一個(gè)64MB的區(qū)域的一次完全回收所需的時(shí)間不到半秒鐘.



并行回收parallel collector:
特點(diǎn):可以利用多核的CPU.
young區(qū)域:同樣還是要暫停應(yīng)用,基本機(jī)制和串行化差不多,不過(guò)是使用多線程.可以加快效率.
old區(qū)域:同串行化.
多核計(jì)算機(jī)上面可以使用.



并行壓縮回收parallel compacting collector:
與并行回收相比,主要是在old區(qū)域有個(gè)新的算法,同時(shí),按白皮書(shū)的說(shuō)法,這種回收最終會(huì)替代并行回收.
young區(qū)域:同并行回收.
old區(qū)域:首先,把old分為幾個(gè)連續(xù)的區(qū)域.然后,在每個(gè)區(qū)域并行的進(jìn)行檢查,標(biāo)記出alive的對(duì)象(先標(biāo)記出可以直接引用的對(duì)象,然后是所有的).然后開(kāi)始對(duì)這些區(qū)域進(jìn)行檢查,得出密集程度(左邊的區(qū)域肯定比右邊的密集),從某個(gè)密集程度不很高的區(qū)域開(kāi)始,并行的對(duì)右邊區(qū)域進(jìn)行壓縮.
適應(yīng)范圍:對(duì)于多核,且對(duì)pause time有要求的環(huán)境下,使用并行壓縮回收比并行回收要好.但是對(duì)于高共享率的服務(wù)器(也就說(shuō)一臺(tái)服務(wù)器運(yùn)行多個(gè)應(yīng)用),由于old區(qū)域的collection較慢,又是多線程,所以一個(gè)應(yīng)用的GC會(huì)對(duì)其他應(yīng)用造成影響.對(duì)應(yīng)的解決方法:可以配置減少并行時(shí)的線程數(shù)目.

并行標(biāo)記清除回收Concurrent Mark Sweep collector:
young區(qū)域:同并行回收.
old區(qū)域:分為幾個(gè)步驟.
Initialmark:在需要執(zhí)行GC時(shí),先暫停應(yīng)用,然后把所有直接引用到的對(duì)象進(jìn)行標(biāo)記.
Concurrentmark:然后繼續(xù)應(yīng)用,并同時(shí)對(duì)已標(biāo)記對(duì)象進(jìn)行檢查,得到所有存活的對(duì)象.
remark:再次暫停應(yīng)用,對(duì)Concurrent mark持續(xù)期間應(yīng)用程序修改了的對(duì)象進(jìn)行檢查(新增的,廢棄的),并標(biāo)記存活對(duì)象.這個(gè)階段持續(xù)時(shí)間較長(zhǎng),因此會(huì)使用多線程.在階段結(jié)束后,所有的存活對(duì)象都被標(biāo)記了,未標(biāo)記的對(duì)象就是垃圾對(duì)象了.
sweep:停止暫停應(yīng)用程序,然后把所有垃圾對(duì)象的空間釋放.



與其他算法的不同點(diǎn):
第一:不執(zhí)行壓縮.不過(guò)會(huì)通過(guò)計(jì)算將來(lái)可能的內(nèi)存需求而合并/分割某些內(nèi)存塊.
第二:不是old區(qū)域要滿了才執(zhí)行GC,而是在空間小于一定程度時(shí)開(kāi)始.
第三:由于沒(méi)執(zhí)行壓縮,因此會(huì)產(chǎn)生碎片.

另外,CMS還可以使用增量運(yùn)行方式,就是在Concurrentmark階段只執(zhí)行一部分工作,然后把資源還給應(yīng)用程序.回收器的工作會(huì)分為幾個(gè)部分并安排在兩次young區(qū)域的回收空閑階段完成.這種模式一般用在對(duì)暫停時(shí)間有要求,同時(shí)處理器數(shù)目不多的情況下(單核或雙核).
總體說(shuō)來(lái),與并行回收相比,CMS降低了old GC的暫停時(shí)間(有時(shí)候效果很顯著),輕微的加長(zhǎng)了young GC的時(shí)間(因?yàn)閷?duì)象從young區(qū)域轉(zhuǎn)到old區(qū)域時(shí)間會(huì)加長(zhǎng):沒(méi)執(zhí)行壓縮,因此要先找到合適的區(qū)域),降低了整個(gè)系統(tǒng)的一些執(zhí)行效率,以及很大的加強(qiáng)了對(duì)于內(nèi)存空間的需求.


一些Java編程的建議

根據(jù)GC的工作原理,,我們可以通過(guò)一些技巧和方式,讓GC運(yùn)行更加有效率,,更加符合應(yīng)用程序的要求,。一些關(guān)于程序設(shè)計(jì)的幾點(diǎn)建議:

1.最基本的建議就是盡早釋放無(wú)用對(duì)象的引用。大多數(shù)程序員在使用臨時(shí)變量的時(shí)候,,都是讓引用變量在退出活動(dòng)域(scope)后,,自動(dòng)設(shè)置為 null.我們?cè)谑褂眠@種方式時(shí)候,必須特別注意一些復(fù)雜的對(duì)象圖,,例如數(shù)組,,隊(duì)列,樹(shù),,圖等,,這些對(duì)象之間有相互引用關(guān)系較為復(fù)雜。對(duì)于這類(lèi)對(duì)象,,GC 回收它們一般效率較低,。如果程序允許,盡早將不用的引用對(duì)象賦為null.這樣可以加速GC的工作,。

2.盡量少用finalize函數(shù),。finalize函數(shù)是Java提供給程序員一個(gè)釋放對(duì)象或資源的機(jī)會(huì)。但是,,它會(huì)加大GC的工作量,,因此盡量少采用finalize方式回收資源。

3.如果需要使用經(jīng)常使用的圖片,,可以使用soft應(yīng)用類(lèi)型,。它可以盡可能將圖片保存在內(nèi)存中,供程序調(diào)用,而不引起OutOfMemory.

4.注意集合數(shù)據(jù)類(lèi)型,,包括數(shù)組,,樹(shù),圖,,鏈表等數(shù)據(jù)結(jié)構(gòu),,這些數(shù)據(jù)結(jié)構(gòu)對(duì)GC來(lái)說(shuō),回收更為復(fù)雜,。另外,,注意一些全局的變量,以及一些靜態(tài)變量,。這些變量往往容易引起懸掛對(duì)象(dangling reference),,造成內(nèi)存浪費(fèi)。

5.當(dāng)程序有一定的等待時(shí)間,,程序員可以手動(dòng)執(zhí)行System.gc(),,通知GC運(yùn)行,但是Java語(yǔ)言規(guī)范并不保證GC一定會(huì)執(zhí)行,。使用增量式GC可以縮短Java程序的暫停時(shí)間,。


參考

j2se 5.0 hotspot 的四種垃圾回收器 - http://blog.csdn.net/dmy_110/article/details/8000007

探秘Java垃圾回收機(jī)制 - http://developer.51cto.com/art/201009/227691.htm

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多