來(lái)自:開(kāi)源中國(guó)(oschina2013)
鏈接:https://www.oschina.net/translate/java-gc
如需轉(zhuǎn)載請(qǐng)注明上述信息,其他信息無(wú)效并視為侵權(quán)
什么是自動(dòng)垃圾回收钾麸?
自動(dòng)垃圾回收是指監(jiān)測(cè)堆內(nèi)存茁影、識(shí)別正在使用或未使用的對(duì)象、然后刪除那些未使用對(duì)象的過(guò)程确沸。正在使用中的對(duì)象捌锭,或者說(shuō)被引用的對(duì)象,是指程序中的某些地方仍然維護(hù)者指向該對(duì)象的指針罗捎。未使用的對(duì)象观谦,或者說(shuō)未被引用的對(duì)象,不再被程序中的任何地方引用桨菜。所以豁状,未被引用的對(duì)象所占用的內(nèi)存可以被回收捉偏。?
在像C這樣的編程語(yǔ)言中,分配和回收內(nèi)存需要手動(dòng)處理泻红。在Java中夭禽,內(nèi)存回收的過(guò)程由垃圾收集器自動(dòng)處理∫曷罚基本過(guò)程可以描述如下讹躯。
第一步:標(biāo)記
這個(gè)過(guò)程的第一步叫做標(biāo)記。這一階段缠劝,垃圾回收器識(shí)別哪些內(nèi)存正在使用潮梯,哪些內(nèi)存未被使用。
被引用的對(duì)象以藍(lán)色展示惨恭。未被引用的對(duì)象以金黃色展示秉馏。在標(biāo)記階段,所有對(duì)象都需要掃描并做出判斷喉恋。如果系統(tǒng)中的所有對(duì)象都必須掃描到沃饶,這將是一個(gè)非常耗時(shí)的過(guò)程。
第二步:常規(guī)刪除
這一階段轻黑,移除所有未被引用的對(duì)象糊肤,保留被引用的對(duì)象,并維護(hù)指向空閑內(nèi)存的指針氓鄙。
內(nèi)存分配器維護(hù)著空閑內(nèi)存塊的引用馆揉,新建對(duì)象的內(nèi)存將在這里被分配。
第二(a)步:刪除并整理
為了進(jìn)一步提高性能抖拦,除了刪除未被引用的對(duì)象升酣,還可以壓縮剩余的被引用對(duì)象(的空間占用)。把被引用的對(duì)象移動(dòng)到一起态罪,會(huì)使得新對(duì)象的內(nèi)存分配更容易噩茄、更快。
為什么使用分代垃圾回收?
如前所述复颈,標(biāo)記并整理所有JVM里的對(duì)象绩聘,效率是很低的。隨著越來(lái)越多的對(duì)象被分配耗啦,對(duì)象列表不斷增長(zhǎng)凿菩,導(dǎo)致垃圾回收時(shí)間越來(lái)越長(zhǎng)。然而帜讲,根據(jù)應(yīng)用程序的經(jīng)驗(yàn)分析衅谷,大多數(shù)的對(duì)象都是短命的。
下面是這類數(shù)據(jù)的一個(gè)例子似将。Y軸表示分配的字節(jié)數(shù)获黔,X軸表示隨著時(shí)間分配的字節(jié)數(shù)蚀苛。
正如你所看到的,隨著時(shí)間的推移肢执,仍然存活的對(duì)象越來(lái)越少枉阵。事實(shí)上译红,大多數(shù)對(duì)象的生命周期都很短预茄,如圖左側(cè)較高的值所示。
JVM分代
從對(duì)象分配行為中學(xué)到的內(nèi)容侦厚,可以用來(lái)提高JVM的性能耻陕。因此,可以考慮將堆分成更小的部分或者幾代刨沦。比如:年輕代诗宣、老年代、持久代想诅。
年輕代是用來(lái)分配和老化所有新對(duì)象的地方召庞。當(dāng)年輕代被填滿,將會(huì)觸發(fā)Minor GC来破。如果對(duì)象死亡率很高M(jìn)inor GC可以優(yōu)化篮灼。年輕代的所有死亡對(duì)象可以被迅速回收。一些存活對(duì)象會(huì)被老化徘禁,最終會(huì)被移動(dòng)到老年代诅诱。
Stop the World——所有Minor GC都會(huì)觸發(fā)“Stop the World”。這意味著所有應(yīng)用程序線程都會(huì)停止送朱,直到操作完成娘荡。Minor GC?總會(huì)觸發(fā)Stop the Word。
老年代用來(lái)保存長(zhǎng)時(shí)間存活的對(duì)象驶沼。通常炮沐,設(shè)置一個(gè)閾值,當(dāng)達(dá)到該年齡時(shí)回怜,年輕代對(duì)象會(huì)被移動(dòng)到老年代大年。最終老年代也會(huì)被回收。這個(gè)事件成為 Major GC鹉戚。
Major GC 也會(huì)觸發(fā)STW(Stop the World)鲜戒。通常,Major GC會(huì)慢很多抹凳,因?yàn)樗婕暗剿写婊顚?duì)象遏餐。所以,對(duì)于響應(yīng)性的應(yīng)用程序赢底,應(yīng)該盡量避免Major GC失都。還要注意柏蘑,Major GC的STW的時(shí)長(zhǎng)受年老代垃圾回收器類型的影響。
永久代包含JVM用于描述應(yīng)用程序中類和方法的元數(shù)據(jù)粹庞。永久代是由JVM在運(yùn)行時(shí)根據(jù)應(yīng)用程序使用的類來(lái)填充的咳焚。此外,Java SE類庫(kù)和方法也存儲(chǔ)在這里庞溜。
如果JVM發(fā)現(xiàn)某些類不再需要革半,并且其他類可能需要空間,則這些類可能會(huì)被回收流码。
世代垃圾收集過(guò)程
現(xiàn)在你已經(jīng)理解了為什么堆被分成不同的代又官,現(xiàn)在是時(shí)候看看這些空間是如何相互作用的。 后面的圖片將介紹JVM中的對(duì)象分配和老化過(guò)程漫试。
首先六敬,將任何新對(duì)象分配給 eden 空間。 兩個(gè) survivor?空間都是空的驾荣。
當(dāng) eden?空間填滿時(shí)外构,會(huì)觸發(fā)輕微的垃圾收集。
引用的對(duì)象被移動(dòng)到第一個(gè) survivor?空間播掷。 清除?eden?空間時(shí)审编,將刪除未引用的對(duì)象。
在下一次Minor GC中叮趴,Eden區(qū)也會(huì)做同樣的操作割笙。刪除未被引用的對(duì)象,并將被引用的對(duì)象移動(dòng)到Survivor區(qū)眯亦。然而伤溉,這里,他們被移動(dòng)到了第二個(gè)Survivor區(qū)(S1)妻率。此外乱顾,第一個(gè)Survivor區(qū)(S0)中,在上一次Minor GC幸存的對(duì)象宫静,會(huì)增加年齡走净,并被移動(dòng)到S1中。待所有幸存對(duì)象都被移動(dòng)到S1后孤里,S0和Eden區(qū)都會(huì)被清空伏伯。注意,Survivor區(qū)中有了不同年齡的對(duì)象捌袜。
在下一次Minor GC中说搅,會(huì)重復(fù)同樣的操作。不過(guò)虏等,這一次Survivor區(qū)會(huì)交換弄唧。被引用的對(duì)象移動(dòng)到S0,适肠。幸存的對(duì)象增加年齡。Eden區(qū)和S1被清空候引。
此幻燈片演示了 promotion侯养。 在較小的GC之后,當(dāng)老化的物體達(dá)到一定的年齡閾值(在該示例中為8)時(shí)澄干,它們從年輕一代晉升到老一代逛揩。
隨著較小的GC持續(xù)發(fā)生,物體將繼續(xù)被推廣到老一代空間傻寂。
所以這幾乎涵蓋了年輕一代的整個(gè)過(guò)程息尺。 最終携兵,將主要對(duì)老一代進(jìn)行GC疾掰,清理并最終壓縮該空間。