深入理解java虛擬機(jī) 摘要(四)--垃圾收集器與內(nèi)存分配策略

深入理解java虛擬機(jī) 摘要


目錄:
一、自動(dòng)內(nèi)存管理機(jī)制

  1. 運(yùn)行時(shí)數(shù)據(jù)區(qū)域
  2. HotSpot虛擬機(jī)對(duì)象探秘
  3. 實(shí)戰(zhàn):OutOfMemoryError異常
  4. 垃圾收集器與內(nèi)存分配策略

一阶女、自動(dòng)內(nèi)存管理機(jī)制


4.垃圾收集器與內(nèi)存分配策略

主要考慮 Java堆和方法區(qū) 內(nèi)存

  • 對(duì)象死亡判斷

    在堆里面存放著Java世界中幾乎所有的對(duì)象實(shí)例甩骏,垃圾收集器在對(duì)堆進(jìn)行回收前香罐,第一件事情就是要確定這些對(duì)象之中哪些還“存活”著牛欢,哪些已經(jīng)“死去”(即不可能再被任何途徑使用的對(duì)象)逸绎。

    1. 引用計(jì)數(shù)算法

    給對(duì)象中添加一個(gè)引用計(jì)數(shù)器惹恃,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加1棺牧;當(dāng)引用失效時(shí)巫糙,計(jì)數(shù)器值就減1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的颊乘。
    主流的Java虛擬機(jī)里面沒(méi)有選用引用計(jì)數(shù)算法來(lái)管理內(nèi)存参淹,其中最主要的原因是它很難解決對(duì)象之間相互循環(huán)引用的問(wèn)題醉锄。

    例子:

    public class Tests {
    public Object instance=null;
    private static final int MB=1024*1024;
    /**
    *這個(gè)成員屬性的唯一意義就是占點(diǎn)內(nèi)存,以便能在GC日志中看清楚是否被回收過(guò)
    */
    public static void main(String[] args){
      Tests objA=new Tests();
      Tests objB=new Tests();
      objA.instance=objB;
      objB.instance=objA;
      objA=null;
      objB=null;
      //假設(shè)在這行發(fā)生GC,objA和objB是否能被回收浙值?
      System.gc();
      }
    }
    

    啟動(dòng)參數(shù)

    -XX:+PrintGCDetails
    

    運(yùn)行結(jié)果(部分)
    [GC (System.gc()) [PSYoungGen: 4601K->1144K(37888K)] 4601K->1152K(123904K), 0.0086625 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
    從運(yùn)行結(jié)果中可以清楚看到恳不,GC日志中包含“4601K->1144K”,意味著虛擬機(jī)并沒(méi)有因?yàn)檫@兩個(gè)對(duì)象互相引用就不回收它們亥鸠,這也從側(cè)面說(shuō)明虛擬機(jī)并不是通過(guò)引用計(jì)數(shù)算法來(lái)判斷對(duì)象是否存活的妆够。

    1. 可達(dá)性分析算法

    在主流的商用程序語(yǔ)言(Java、C#负蚊,甚至包括前面提到的古老的Lisp)的主流實(shí)現(xiàn)中神妹,都是稱通過(guò)可達(dá)性分析(Reachability Analysis)來(lái)判定對(duì)象是否存活的。這個(gè)算法的基本思路就是通過(guò)一系列的稱為“GC Roots”的對(duì)象作為起始點(diǎn)家妆,從這些節(jié)點(diǎn)開(kāi)始向下搜索鸵荠,搜索所走過(guò)的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí)伤极,則證明此對(duì)象是不可用的蛹找。

    在Java語(yǔ)言中,可作為GC Roots的對(duì)象包括下面幾種:
    虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象哨坪。
    方法區(qū)中類靜態(tài)屬性引用的對(duì)象庸疾。
    方法區(qū)中常量引用的對(duì)象。
    本地方法棧中JNI(即一般說(shuō)的Native方法)引用的對(duì)象当编。

    在JDK 1.2之后届慈,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用(StrongReference)忿偷、軟引用(Soft Reference)金顿、弱引用(Weak Reference)、虛引用(PhantomReference)4種鲤桥,這4種引用強(qiáng)度依次逐漸減弱揍拆。

  • 垃圾收集算法

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

    最基礎(chǔ)的收集算法是“標(biāo)記-清除”(Mark-Sweep)算法,如同它的名字一樣茶凳,算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象嫂拴,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象,它的標(biāo)記過(guò)程其實(shí)在前一節(jié)講述對(duì)象標(biāo)記判定時(shí)已經(jīng)介紹過(guò)了贮喧。之所以說(shuō)它是最基礎(chǔ)的收集算法顷牌,是因?yàn)楹罄m(xù)的收集算法都是基于這種思路并對(duì)其不足進(jìn)行改進(jìn)而得到的。
    它的主要不足有兩個(gè):一個(gè)是效率問(wèn)題塞淹,標(biāo)記和清除兩個(gè)過(guò)程的效率都不高窟蓝;另一個(gè)是空間問(wèn)題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過(guò)程中需要分配較大對(duì)象時(shí)运挫,無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作状共。

    1. 復(fù)制算法

    為了解決效率問(wèn)題,一種稱為“復(fù)制”(Copying)的收集算法出現(xiàn)了谁帕,它將可用內(nèi)存按容量劃分為大小相等的兩塊峡继,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了匈挖,就將還存活著的對(duì)象復(fù)制到另外一塊上面碾牌,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。這樣使得每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收儡循,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況舶吗,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可择膝,實(shí)現(xiàn)簡(jiǎn)單誓琼,運(yùn)行高效。只是這種算法的代價(jià)是將內(nèi)存縮小為了原來(lái)的一半肴捉,未免太高了一點(diǎn)腹侣。

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

    復(fù)制收集算法在對(duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作,效率將會(huì)變低齿穗。更關(guān)鍵的是傲隶,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保窃页,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都100%存活的極端情況伦籍,所以在老年代一般不能直接選用這種算法。
    根據(jù)老年代的特點(diǎn)腮出,有人提出了另外一種“標(biāo)記-整理”(Mark-Compact)算法,標(biāo)記過(guò)程仍然與“標(biāo)記-清除”算法一樣芝薇,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理胚嘲,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存洛二,

    1. 分代收集算法

    當(dāng)前商業(yè)虛擬機(jī)的垃圾收集都采用“分代收集”(Generational Collection)算法馋劈,這種算法并沒(méi)有什么新的思想,只是根據(jù)對(duì)象存活周期的不同將內(nèi)存劃分為幾塊晾嘶。一般是把Java堆分為新生代和老年代妓雾,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴āT谛律欣萦兀看卫占瘯r(shí)都發(fā)現(xiàn)有大批對(duì)象死去械姻,只有少量存活,那就選用復(fù)制算法机断,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集楷拳。而老年代中因?yàn)閷?duì)象存活率高绣夺、沒(méi)有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用“標(biāo)記—清理”或者“標(biāo)記—整理”算法來(lái)進(jìn)行回收欢揖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陶耍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子她混,更是在濱河造成了極大的恐慌烈钞,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坤按,死亡現(xiàn)場(chǎng)離奇詭異毯欣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)晋涣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門仪媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谢鹊,你說(shuō)我怎么就攤上這事操骡∽萸蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拖云。 經(jīng)常有香客問(wèn)我,道長(zhǎng)倦踢,這世上最難降的妖魔是什么炕倘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮瘤运,結(jié)果婚禮上窍霞,老公的妹妹穿的比我還像新娘。我一直安慰自己拯坟,他們只是感情好但金,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著郁季,像睡著了一般冷溃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梦裂,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天似枕,我揣著相機(jī)與錄音,去河邊找鬼年柠。 笑死凿歼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毅往,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼牵咙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了攀唯?” 一聲冷哼從身側(cè)響起洁桌,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侯嘀,沒(méi)想到半個(gè)月后另凌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡戒幔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吠谢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诗茎。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡工坊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出敢订,到底是詐尸還是另有隱情王污,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布楚午,位于F島的核電站昭齐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矾柜。R本人自食惡果不足惜阱驾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怪蔑。 院中可真熱鬧里覆,春花似錦、人聲如沸缆瓣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捆愁。三九已至,卻和暖如春窟却,著一層夾襖步出監(jiān)牢的瞬間昼丑,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工夸赫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菩帝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像呼奢,于是被迫代替她去往敵國(guó)和親宜雀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容