亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

聊聊GC

developerworks / 3181人閱讀

摘要:復(fù)制這一工作所花費(fèi)的時(shí)間,在對象存活率達(dá)到一定程度時(shí),將會變的不可忽視。針對老年代老年代的特點(diǎn)是區(qū)域較大,對像存活率高。這種情況,存在大量存活率高的對像,復(fù)制算法明顯變得不合適。

GC(Garbage Collection)即Java垃圾回收機(jī)制,是Java與C++的主要區(qū)別之一,作為Java開發(fā)者,一般不需要專門編寫內(nèi)存回收和垃圾清理代碼,對內(nèi)存泄露和溢出的問題,也不需要像C++程序員那樣戰(zhàn)戰(zhàn)兢兢,就是因?yàn)镴ava有這個(gè)方便的機(jī)制。

為了對GC有一個(gè)直觀的認(rèn)識,先來一張圖:

對圖中各種名詞不熟悉的話,請參照我的上一篇文章:JVM小結(jié)

GC算法總體概述

JVM在進(jìn)行GC時(shí),并非每次都對上面三個(gè)內(nèi)存區(qū)域一起回收的,大部分時(shí)候回收的都是指新生代。因此GC按照回收的區(qū)域又分了兩種類型,一種是普通GC(minor GC),一種是全局GC(major GC or Full GC)

普通GC(minor GC):只針對新生代區(qū)域的GC。

全局GC(major GC or Full GC):針對年老代的GC,偶爾伴隨對新生代的GC以及對永久代的GC。

四大算法 1. 復(fù)制算法(Copying)

年輕代中使用的是Minor GC,這種GC算法采用的是復(fù)制算法(Copying)。

此圖代表了堆的內(nèi)存結(jié)構(gòu)

HotSpot JVM把年輕代分為了三部分:1個(gè)Eden區(qū)和2個(gè)Survivor區(qū)(分別叫from和to)。默認(rèn)比例為8:1:1,一般情況下,新創(chuàng)建的對象都會被分配到Eden區(qū)(一些大對象特殊處理),這些對象經(jīng)過第一次Minor GC后,如果仍然存活,將會被移到Survivor區(qū)。對象在Survivor區(qū)中每熬過一次Minor GC,年齡就會增加1歲,當(dāng)它的年齡增加到一定程度時(shí),就會被移動(dòng)到年老代中。因?yàn)槟贻p代中的對象基本都是朝生夕死的(80%以上),所以在年輕代的垃圾回收算法使用的是復(fù)制算法,復(fù)制算法的基本思想就是將內(nèi)存分為兩塊,每次只用其中一塊,當(dāng)這一塊內(nèi)存用完,就將還活著的對象復(fù)制到另外一塊上面。復(fù)制算法不會產(chǎn)生內(nèi)存碎片。

在GC開始的時(shí)候,對象只會存在于Eden區(qū)和名為From的Survivor區(qū),Survivor區(qū)To是空的。緊接著進(jìn)行GC,Eden區(qū)中所有存活的對象都會被復(fù)制到To,而在From區(qū)中,仍存活的對象會根據(jù)他們的年齡值來決定去向。年齡達(dá)到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設(shè)置)的對象會被移動(dòng)到年老代中,沒有達(dá)到閾值的對象會被復(fù)制到To區(qū)域。經(jīng)過這次GC后,Eden區(qū)和From區(qū)已經(jīng)被清空。這個(gè)時(shí)候,FromTo會交換他們的角色,也就是新的To就是上次GC前的From,新的From就是上次GC前的To。不管怎樣,都會保證名為To的Survivor區(qū)域是空的。Minor GC會一直重復(fù)這樣的過程,直到To區(qū)被填滿,To區(qū)被填滿之后,會將所有對象移動(dòng)到年老代中。

-XX:MaxTenuringThreshold  設(shè)置對象在新生代中存活的次數(shù)


因?yàn)镋den區(qū)對象一般存活率較低,一般的,使用兩塊10%的內(nèi)存作為空閑和活動(dòng)區(qū)間,而另外80%的內(nèi)存,則是用來給新建對象分配內(nèi)存的。一旦發(fā)生GC,將10%的from活動(dòng)區(qū)間與另外80%中存活的eden對象轉(zhuǎn)移到10%的to空閑區(qū)間,接下來,將之前90%的內(nèi)存全部釋放,以此類推。

劣勢:
復(fù)制算法彌補(bǔ)了標(biāo)記/清除算法中,內(nèi)存布局混亂的缺點(diǎn)。不過與此同時(shí),它的缺點(diǎn)也是相當(dāng)明顯的:

它浪費(fèi)了一半的內(nèi)存。

如果對象的存活率很高,我們可以極端一點(diǎn),假設(shè)是100%存活,那么我們需要將所有對象都復(fù)制一遍,并將所有引用地址重置一遍。復(fù)制這一工作所花費(fèi)的時(shí)間,在對象存活率達(dá)到一定程度時(shí),將會變的不可忽視。 所以從以上描述不難看出,復(fù)制算法要想使用,最起碼對象的存活率要非常低才行,而且最重要的是,我們必須要克服50%內(nèi)存的浪費(fèi)。

2. 標(biāo)記清除(Mark-Sweep)

老年代一般是由標(biāo)記清除或者是標(biāo)記清除與標(biāo)記整理的混合實(shí)現(xiàn)。

當(dāng)堆中的有效內(nèi)存空間(available memory)被耗盡的時(shí)候,就會停止整個(gè)程序(也被稱為stop the world),然后進(jìn)行兩項(xiàng)工作,第一項(xiàng)則是標(biāo)記,第二項(xiàng)則是清除。

標(biāo)記:從引用根節(jié)點(diǎn)開始標(biāo)記所有被引用的對象。標(biāo)記的過程其實(shí)就是遍歷所有的GC Roots,然后將所有GC Roots可達(dá)的對象 標(biāo)記為存活的對象。

清除:遍歷整個(gè)堆,把未標(biāo)記的對象清除。

通俗來講,就是當(dāng)程序運(yùn)行期間,若可以使用的內(nèi)存被耗盡的時(shí)候,GC線程就會被觸發(fā)并將程序暫停,隨后將依舊存活的對象標(biāo)記一遍,最終再將堆中所有沒被標(biāo)記的對象全部清除掉,接下來便讓程序恢復(fù)運(yùn)行。

缺點(diǎn):

效率比較低(遞歸與全堆對象遍歷),而且在進(jìn)行GC的時(shí)候,需要停止應(yīng)用程序,這會導(dǎo)致用戶體驗(yàn)非常差。

這種方式清理出來的空閑內(nèi)存是不連續(xù)的,我們的死亡對象都是隨即的出現(xiàn)在內(nèi)存的各個(gè)角落的,把它們清除之后,內(nèi)存的布局自然會散亂。而為了應(yīng)付這一點(diǎn),JVM就不得不維持一個(gè)內(nèi)存的空閑列表,這又是一種開銷。而且在分配數(shù)組對象的時(shí)候,尋找連續(xù)的內(nèi)存空間會有難度。

3. 標(biāo)記壓縮(Mark-Compact)

老年代一般是由標(biāo)記清除或者是標(biāo)記清除與標(biāo)記壓縮的混合實(shí)現(xiàn)。

在整理壓縮階段,不再對標(biāo)記的對像做回收,而是通過所有存活對像都向一端移動(dòng),然后直接清除邊界以外的內(nèi)存。
可以看到,標(biāo)記的存活對象將會被整理,按照內(nèi)存地址依次排列,而未被標(biāo)記的內(nèi)存會被清理掉。如此一來,當(dāng)我們需要給新對象分配內(nèi)存時(shí),JVM只需要持有一個(gè)內(nèi)存的起始地址即可,這比維護(hù)一個(gè)空閑列表顯然少了許多開銷。
標(biāo)記/整理算法不僅可以彌補(bǔ)標(biāo)記/清除算法當(dāng)中,內(nèi)存區(qū)域分散的缺點(diǎn),也消除了復(fù)制算法當(dāng)中,內(nèi)存減半的高額代價(jià)。

劣勢:標(biāo)記/整理算法唯一的缺點(diǎn)就是效率也不高,不僅要標(biāo)記所有存活對象,還要整理所有存活對象的引用地址。從效率上來說,標(biāo)記/整理算法要低于復(fù)制算法。

4. 標(biāo)記清除壓縮(Mark-Sweep-Compact)

多提一嘴:引用計(jì)數(shù)法

這種算法最直接簡單,它維護(hù)了一個(gè)引用計(jì)數(shù)器,對象被引用一次計(jì)數(shù)器+1,少一次-1,如果計(jì)數(shù)器為0則對象就被視為垃圾進(jìn)行回收。

注:JVM的實(shí)現(xiàn)一般不采用這種方式。

劣勢:

每次對對象賦值時(shí)均需維護(hù)計(jì)數(shù)器,且計(jì)數(shù)器本身有一定消耗。

較難處理循環(huán)引用。

小結(jié)

內(nèi)存效率:復(fù)制算法>標(biāo)記清除算法>標(biāo)記整理算法(此處的效率只是簡單的對比時(shí)間復(fù)雜度,實(shí)際情況不一定如此)。
內(nèi)存整齊度:復(fù)制算法==標(biāo)記整理算法>標(biāo)記清除算法。
內(nèi)存利用率:標(biāo)記整理算法==標(biāo)記清除算法>復(fù)制算法。
可以看出,效率上來說,復(fù)制算法最快,但是卻浪費(fèi)了太多內(nèi)存,而為了盡量兼顧上面所提到的三個(gè)指標(biāo),標(biāo)記/整理算法相對來說更平滑一些,但效率上依然不盡如人意,它比復(fù)制算法多了一個(gè)標(biāo)記的階段,又比標(biāo)記/清除多了一個(gè)整理內(nèi)存的過程。

有沒有最好的算法呢?只能說:沒有最好的,只有最適合的——分代收集:

針對年輕代

年輕代特點(diǎn)是區(qū)域相對老年代較小,對像存活率低。這種情況復(fù)制算法的回收整理,速度是最快的。復(fù)制算法的效率只和當(dāng)前存活對像大小有關(guān),因而很適用于年輕代的回收。而復(fù)制算法內(nèi)存利用率不高的問題,通過hotspot中的兩個(gè)survivor的設(shè)計(jì)得到緩解。

針對老年代

老年代的特點(diǎn)是區(qū)域較大,對像存活率高。
這種情況,存在大量存活率高的對像,復(fù)制算法明顯變得不合適。一般是由標(biāo)記清除或者是標(biāo)記清除與標(biāo)記整理的混合實(shí)現(xiàn)。
Mark階段的開銷與存活對像的數(shù)量成正比,這點(diǎn)上說來,對于老年代,標(biāo)記清除或者標(biāo)記整理有一些不符,但可以通過多核/線程利用,對并發(fā)、并行的形式提標(biāo)記效率。
Sweep階段的開銷與所管理區(qū)域的大小形正相關(guān),但Sweep“就地處決”的特點(diǎn),回收的過程沒有對像的移動(dòng)。使其相對其它有對像移動(dòng)步驟的回收算法,仍然是效率最好的。但是需要解決內(nèi)存碎片問題。
Compact階段的開銷與存活對像的數(shù)據(jù)成開比,如上一條所描述,對于大量對像的移動(dòng)是很大開銷的,做為老年代的第一選擇并不合適。
基于上面的考慮,老年代一般是由標(biāo)記清除或者是標(biāo)記清除與標(biāo)記整理的混合實(shí)現(xiàn)。以hotspot中的CMS回收器為例,CMS是基于Mark-Sweep實(shí)現(xiàn)的,對于對像的回收效率很高,而對于碎片問題,CMS采用基于Mark-Compact算法的Serial Old回收器做為補(bǔ)償措施:當(dāng)內(nèi)存回收不佳(碎片導(dǎo)致的Concurrent Mode Failure時(shí)),將采用Serial Old執(zhí)行Full GC以達(dá)到對老年代內(nèi)存的整理。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/68363.html

相關(guān)文章

  • 聊聊Garbage Collector的SATB

    摘要:序本主要研究一下的在進(jìn)行的都采用了的技術(shù)面向的垃圾收集器,它的主要有包括這個(gè)階段用到了進(jìn)行包括在進(jìn)行的時(shí)候采用了的技術(shù)全稱為,其要點(diǎn)如下的過程就是遍歷標(biāo)記,采用的是三色標(biāo)記算法,這三種顏色為表示還未訪問到訪問到但是它用到的引用還沒 序 本主要研究一下Garbage Collector的SATB CMS、G1、Shenandoah在進(jìn)行concurrent marking的都采用了SAT...

    iflove 評論0 收藏0
  • 【Copy攻城獅日志】聊聊JavaScript heap out of memory

    摘要:當(dāng)時(shí),如果老生區(qū)大小超過設(shè)定的值時(shí),就會報(bào)錯(cuò)。一般是無限制增長的數(shù)組無限制設(shè)置屬性和值大循環(huán)等出處林小新。這部分由于攻城獅并為深入,可以參考如何定位的內(nèi)存泄漏內(nèi)存泄漏以及定位 showImg(https://segmentfault.com/img/bVbnysD?w=649&h=658);↑開局一張圖,故事全靠編↑ 從一次宕機(jī)說起 這是一個(gè)很狗血的故事,故事的開頭是一個(gè)項(xiàng)目,這個(gè)項(xiàng)...

    paulquei 評論0 收藏0
  • ES6 系列之 WeakMap

    摘要:一個(gè)對象若只被弱引用所引用,則被認(rèn)為是不可訪問或弱可訪問的,并因此可能在任何時(shí)刻被回收。也就是說,一旦不再需要,里面的鍵名對象和所對應(yīng)的鍵值對會自動(dòng)消失,不用手動(dòng)刪除引用。如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,請?wù)必給予指正,十分感謝。 前言 我們先從 WeakMap 的特性說起,然后聊聊 WeakMap 的一些應(yīng)用場景。 特性 1. WeakMap 只接受對象作為鍵名 const map = ...

    CollinPeng 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<