Java&Android 基礎(chǔ)知識梳理(4) - 垃圾收集器與內(nèi)存分配策略

一该贾、概述

GC需要考慮的三個問題:

  • 哪些內(nèi)存需要回收
  • 什么時候回收
  • 如何回收

在分析內(nèi)存區(qū)域的時候诉稍,我們把Java運行時數(shù)據(jù)區(qū)分為兩個部分:

  • 程序計數(shù)器赶熟、虛擬機棧茫负、本地方法棧:每個棧幀中分配多少內(nèi)存在類結(jié)構(gòu)確定下來就已知破停,因此這些區(qū)域的內(nèi)存分配和回收具備確定性翅楼,方法結(jié)束或線程結(jié)束時,內(nèi)存就跟著被回收了真慢。
  • Java堆毅臊、方法區(qū):由于一個接口中的多個實現(xiàn)類需要的內(nèi)存可能不一樣,一個方法中的多個分支需要的內(nèi)存也不一樣黑界,只有在程序處于運行期間才能知道會創(chuàng)建哪些對象管嬉,因此這些區(qū)域的內(nèi)存分配和回收是動態(tài)的。

二朗鸠、如何判斷哪些是“存活”的實例

2.1 引用的分類

引用的定義:如果reference類型的數(shù)據(jù)中存儲的數(shù)值代表的另外一塊內(nèi)存的起始地址蚯撩,就稱這塊內(nèi)存代表引用。
引用的分類:

  • 強引用(Object a = new Object()):只要強引用存在烛占,垃圾回收器永遠不會回收掉被引用的對象胎挎。
  • 軟引用(SoftReference):有用但并非必須,在系統(tǒng)將要發(fā)生OOM異常之前忆家,將會把這些對象列進回收范圍中進行第二次回收犹菇。
  • 弱引用(WeakReference):非必須對象,被弱引用的對象只能生存到下一次垃圾收集發(fā)生前弦赖。
  • 虛引用(PhantomReference):不會對生存時間產(chǎn)生影響项栏,也無法通過虛引用來取得一個對象實例,設(shè)置虛引用的唯一目的就是能在這個對象被垃圾回收器回收時收到一個系統(tǒng)通知蹬竖。

2.2 引用計數(shù)法

給對象添加一個引用計數(shù)器沼沈,當(dāng)有一個地方引用它時就加一流酬,引用失效時就減一,當(dāng)計數(shù)器的值為零時表示它不可用列另。
但是它無法解決相互循環(huán)引用問題芽腾。

2.3 可達性分析

通過一系列的稱為GC Roots的對象作為起始點,從這些節(jié)點開始向下搜索页衙,所走過的路徑稱為引用鏈摊滔。當(dāng)一個對象到GC Roots沒有任何引用鏈時,表示這個對象不可用店乐,GC Roots的類型有:

  • 虛擬機棧中的局部變量表中引用的對象艰躺。
  • 方法區(qū)中類靜態(tài)屬性引用的對象。
  • 方法區(qū)中常量引用的對象眨八。
  • 本地方法棧中JNI引用的對象腺兴。

2.4 finalize方法對于內(nèi)存回收的影響

當(dāng)某個對象在經(jīng)過可達性分析后,發(fā)現(xiàn)它到GC Roots沒有任何引用鏈時廉侧,那么它會被第一次標(biāo)記页响,并進行第一次篩選,篩選的結(jié)果有兩種情況:

  • 沒有覆蓋finalize()方法或者虛擬機已經(jīng)調(diào)用過它的finalize()方法:直接回收段誊。
  • 其它情況:把這個對象放置在一個F-Queue的隊列中闰蚕,并在稍后由一個由虛擬機自動建立的、低優(yōu)先級的Finalizer線程去執(zhí)行這個對象的finalize()方法连舍,如對象要在finalize方法中拯救自己没陡,只要重新與引用鏈的某個變量關(guān)聯(lián)即可,那么在第二次標(biāo)記時它將被移出“即將回收”的集合烟瞧,否則它將被回收诗鸭。

這種方法代價高昂,不確定性大参滴,無法保證各個對象的調(diào)用順序强岸,因此可以忘記這個方法的存在。

三砾赔、方法區(qū)的回收

對于方法區(qū)(HotSpot中的永久代)主要回收兩部分內(nèi)容:廢棄常量和無用的類蝌箍。

  • 廢棄常量
    以常量池中字面量的回收為例,如果一個字符串abc被放入了常量池中暴心,但是沒有任何一個String對象引用它妓盲,那么就會被清理出常量池,常量池中其它類(接口)专普、方法悯衬、字段的符號引用也類似。

  • 類檀夹,同時滿足三個條件:

    • 該類的所有實例已經(jīng)被回收
    • 加載該類的ClassLoader已經(jīng)被回收
    • 該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用筋粗,無法在任何地方通過反射訪問該類的方法策橘。

四、垃圾收集算法基礎(chǔ)

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

  • 概念
    首先標(biāo)記出所有需要回收的對象娜亿,在標(biāo)記完成后統(tǒng)一進行回收丽已。
  • 缺點:
    • 標(biāo)記和清除兩個過程效率不高。
    • 產(chǎn)生內(nèi)存碎片买决,導(dǎo)致需要分配較大對象時沛婴,無法找到足夠的連續(xù)內(nèi)存而需要觸發(fā)一次GC操作。

4.2 復(fù)制算法

  • 概念
    將可用內(nèi)存劃分為大小相等的兩塊督赤,每次只使用其中的一塊嘁灯,當(dāng)一塊內(nèi)存用完了。則觸發(fā)一次GC操作躲舌,將活著的對象復(fù)制到另一塊上旁仿,然后再把已使用的內(nèi)存空間一次清理掉。

  • 缺點
    將內(nèi)存縮小為了原來的一半孽糖。

  • 現(xiàn)在商業(yè)虛擬機采用這種算法的改良版來實現(xiàn)新生代的回收
    它把內(nèi)存按8:1:1分為Eden/survivor0/survivor1三塊:
    需要分配內(nèi)存時,首先嘗試在Eden區(qū)分配毅贮,如果Eden區(qū)無法分配办悟,那么嘗試把活著的對象放到survivor0中去:

  • 如果survivor0可以放入,那么放入之后清除Eden區(qū)滩褥。

  • 如果survivor0不可以放入病蛉,那么嘗試把Edensurvivor0的存活對象放到survivor1中:

    • 如果survivor1可以放入,那么放入survivor1之后清除Edensurvivor0瑰煎,之后再把survivor1中的對象復(fù)制到survivor0中铺然,保持survivor1一直為空。
    • 如果survivor1不可以放入酒甸,那么直接把它們放入到老年代中魄健,并清除Edensurvivor0,這個過程也稱為分配擔(dān)保插勤。
  • 適用情況
    由于復(fù)制算法在對象成活率較高時沽瘦,需要較多的復(fù)制操作,效率會變低农尖,所以在老年代中不能采用該算法析恋。

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

  • 概念
    和標(biāo)記 - 清除算法類似,但后續(xù)步驟不是直接對可回收對象進行清理盛卡,而是讓所有存活的對象都向一端移動助隧,然后直接清除掉端邊界以外的內(nèi)存。
  • 優(yōu)點
    解決了標(biāo)記- 清除算法導(dǎo)致的內(nèi)存碎片問題在存活率較高時復(fù)制算法效率低的問題滑沧。

4.4 分代收集算法

當(dāng)前商業(yè)虛擬機采用的方式并村,根據(jù)對象存活周期的不同將內(nèi)存劃分為幾塊巍实,一般是新生代和老年代:

  • 新生代:每次垃圾收集時只有少量存活,選用復(fù)制算法的改良版橘霎,也就是上面說到的Eden/survivor0/survivor1的分配方式蔫浆。
  • 老年代:對象存活率較高,且沒有分配擔(dān)保姐叁,必須用標(biāo)記 - 清除或標(biāo)記 - 整理算法來實現(xiàn)瓦盛。

五、Minor GCMajor GC/Full GC

  • Minor GC:發(fā)生在新生代的垃圾回收動作外潜,非常頻繁原环,回收速度也較快,采用的垃圾收集器有Serial处窥、ParNew嘱吗、Parallel Scavenge
  • Major GC/Full GC:發(fā)生在老年代的GC滔驾,經(jīng)常伴隨至少一次的Minor GC谒麦,Major GC的速度一般會比Minor GC慢十倍以上,采用的垃圾收集器有CMS哆致、Serial Old绕德、Parallel Old

六摊阀、對象分配的原則

  • 對象優(yōu)先在Eden區(qū)分配
    當(dāng)Eden區(qū)沒有足夠空間耻蛇,觸發(fā)一次Minor GC

  • 大對象直接進入老年代
    例如很長的字符串以及數(shù)組胞此,經(jīng)常出現(xiàn)大對象容易導(dǎo)致內(nèi)存還有不少空間時就提前觸發(fā)垃圾收集以獲取足夠的連續(xù)空間來“安置”它們臣咖。

  • 長期存活的對象將進入老年代
    如果Eden區(qū)出生并進過第一次Minor GC后,仍然存活漱牵,并且被成功復(fù)制到survivor區(qū)中夺蛇,那么對象年齡變?yōu)橐唬?dāng)對象在survivor中每熬過一次Minor GC布疙,年齡就增加一蚊惯,當(dāng)年齡增加到一定程度,就會晉升到老年代中灵临。

  • 動態(tài)對象年齡綁定
    如果survivor空間中相同年齡所有對象大小的總和大于survivor空間的一半截型,年齡大于或等于該年齡的對象就可以進入老年代,無須到達要求的年齡儒溉。

  • 空間分配擔(dān)保
    在發(fā)生Minor GC前宦焦,檢查老年代最大可用連續(xù)空間是否大于新生代所有對象總空間:

  • 大于,那么操作是安全的,不對老年代進行Full GC波闹。

  • 小于酝豪,檢查HandlePromotionFailure設(shè)置值是否允許失敗:

    • 允許:檢查老年代最大可用連續(xù)空間是否大于歷次晉升到老年代對象的平均大芯椤:
      • 大于:不對老年代進行Full GC孵淘。在這之后,因為有可能出現(xiàn)某次存活對象激增的情況歹篓,這種屬于冒險行為瘫证,如果出現(xiàn)了擔(dān)保失敗(也就是Edensurvivor0的存活對象既無法放入survivor1庄撮,也無法放入老年代的連續(xù)空間中)背捌,那么會在失敗之后對老年代進行Full GC
      • 小于:先對老年代進行一次Full GC洞斯。
    • 不允許:先對老年代執(zhí)行一次Full GC毡庆。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市烙如,隨后出現(xiàn)的幾起案子么抗,更是在濱河造成了極大的恐慌,老刑警劉巖亚铁,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乖坠,死亡現(xiàn)場離奇詭異,居然都是意外死亡刀闷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門仰迁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甸昏,“玉大人,你說我怎么就攤上這事徐许∈┟郏” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵雌隅,是天一觀的道長翻默。 經(jīng)常有香客問我,道長恰起,這世上最難降的妖魔是什么修械? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮检盼,結(jié)果婚禮上肯污,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好蹦渣,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布哄芜。 她就那樣靜靜地躺著,像睡著了一般柬唯。 火紅的嫁衣襯著肌膚如雪认臊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天锄奢,我揣著相機與錄音失晴,去河邊找鬼。 笑死斟薇,一個胖子當(dāng)著我的面吹牛师坎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堪滨,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼胯陋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了袱箱?” 一聲冷哼從身側(cè)響起遏乔,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎发笔,沒想到半個月后盟萨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡了讨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年捻激,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片前计。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡胞谭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出男杈,到底是詐尸還是另有隱情丈屹,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布伶棒,位于F島的核電站旺垒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肤无。R本人自食惡果不足惜先蒋,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宛渐。 院中可真熱鬧鞭达,春花似錦司忱、人聲如沸塑煎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽得糜。三九已至叨襟,卻和暖如春繁扎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糊闽。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工梳玫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人右犹。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓提澎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親念链。 傳聞我的和親對象是個殘疾皇子盼忌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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