垃圾收集基礎(chǔ)概念

一、概述

1.為什么要了解GC

當(dāng)需要排查各種內(nèi)存溢出蝶念、內(nèi)存泄漏問題時(shí)翰蠢,當(dāng)GC成為系統(tǒng)達(dá)到高并發(fā)量的瓶頸時(shí),就需要對(duì)這些成熟的技術(shù)實(shí)施必要的監(jiān)控和調(diào)節(jié)服赎。

2. GC了解對(duì)象

  • 主要研究:Java堆葵蒂、方法區(qū)
    程序處于運(yùn)行期間才知道會(huì)創(chuàng)建哪些對(duì)象,這部分的內(nèi)存分配和回收都是動(dòng)態(tài)的重虑。
  • 不需要過多考慮:程序計(jì)數(shù)器践付、虛擬機(jī)棧、本地方法棧
    這些區(qū)域的內(nèi)存分配和回收都具備確定性缺厉,方法結(jié)束或線程結(jié)束時(shí)內(nèi)存自然就回收了永高。

二、回收對(duì)象確定算法

1. 引用

JDK1.2前

引用:如果reference類型的數(shù)據(jù)中存儲(chǔ)的數(shù)值代表的是另外一塊內(nèi)存的起始地址提针。

缺陷:對(duì)象只存在被引用命爬、沒有被引用兩種狀態(tài)。

JDK1.2后

對(duì)引用的概念進(jìn)行擴(kuò)充辐脖,分為了四種引用饲宛,強(qiáng)調(diào)依次減弱。

  1. 強(qiáng)引用:只要存在嗜价,垃圾收集器就不會(huì)回收掉被引用的對(duì)象艇抠。

  2. 軟引用(SoftReference):在內(nèi)存溢出之前,將這些對(duì)象列入回收范圍之中久锥,進(jìn)行第二次回收家淤,回收后還沒有足夠內(nèi)存,才會(huì)拋出內(nèi)存溢出異常奴拦。

  3. 弱引用(WeakReference):垃圾收集器工作時(shí)媒鼓,無論內(nèi)存是否足夠,都會(huì)回收只被弱引用關(guān)聯(lián)的對(duì)象错妖。

  4. 虛引用(PhantomReference):完全不會(huì)對(duì)其對(duì)象的生存時(shí)間構(gòu)成影響绿鸣,也無法通過虛引用取得一個(gè)對(duì)象的實(shí)例。唯一目的是在這個(gè)對(duì)象被回收時(shí)收到一個(gè)系統(tǒng)通知暂氯。

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

給對(duì)象添加一個(gè)引用計(jì)數(shù)器潮模,有一個(gè)引用它就加一,當(dāng)計(jì)數(shù)器為0時(shí)就是不可能再被使用痴施。

優(yōu)點(diǎn)
  • 實(shí)現(xiàn)簡單
  • 判定效率高
缺點(diǎn)
  • 很難解決對(duì)象間相互循環(huán)引用的問題擎厢。

因?yàn)檫@一點(diǎn)究流,主流Java虛擬機(jī)沒有選用引用計(jì)數(shù)算法來管理內(nèi)存的。

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

通過一系列GC Roots的對(duì)象作為起始點(diǎn)动遭,從這些節(jié)點(diǎn)向下搜索芬探,搜索走過的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒有任何引用鏈相連時(shí)(GC Roots到這個(gè)對(duì)象不可達(dá))厘惦,則此對(duì)象是不可用的偷仿。

如圖object5和6,雖然6是有引用指向其的宵蕉,但是因?yàn)閷?duì)GC Roots不可達(dá)酝静,所以此對(duì)象不可用。

GC Roots對(duì)象
  • 虛擬機(jī)棧中引用的對(duì)象羡玛。
  • 方法區(qū)中類靜態(tài)屬性引用的對(duì)象别智。
  • 方法區(qū)中常量引用的對(duì)象。
  • 本地方法棧中JNI引用的對(duì)象稼稿。

4. 兩次標(biāo)記過程

宣告一個(gè)對(duì)象需要回收之前薄榛,至少經(jīng)歷兩次標(biāo)記過程。

  1. 可達(dá)性分析后發(fā)現(xiàn)沒有與GC Roots相連時(shí)渺杉,第一次被標(biāo)記蛇数。
  2. 篩選有必要執(zhí)行finalize()的對(duì)象。
  3. 有必要執(zhí)行的對(duì)象放入F-Queue是越,有虛擬機(jī)自動(dòng)建立、優(yōu)先級(jí)低的線程執(zhí)行它碌上。

雖然會(huì)執(zhí)行它倚评,但并不一定會(huì)等待它運(yùn)行結(jié)束。防止死循環(huán)導(dǎo)致F-Queue隊(duì)列處于等待馏予,導(dǎo)致內(nèi)存回收系統(tǒng)崩潰天梧。

  1. 看finalize()執(zhí)行情況
    • 如果在執(zhí)行finalize()中重新引用到引用鏈上,在第二次標(biāo)記時(shí)會(huì)移出回收集合霞丧。
    • 如果沒有連接上呢岗,就會(huì)被真正回收。

一個(gè)對(duì)象的finalize()方法只會(huì)被調(diào)用一次蛹尝,所以一次逃脫回收后后豫,在下一次回收時(shí)將不再會(huì)執(zhí)行finalize()。

5. 方法區(qū)的回收

方法區(qū)的回收性價(jià)比會(huì)比Java堆低很多突那。

主要回收目標(biāo)
  • 廢棄常量
  • 無用的類
常量的回收條件

字符串為例挫酿,如果沒有String對(duì)象引用常量池的某個(gè)常量,也沒有其他地方應(yīng)用這個(gè)常量時(shí)愕难,就會(huì)將此常量清理出常量池早龟。

常量池中其他類(接口)惫霸、方法、字段的符號(hào)引用也類似葱弟。

類的回收條件
  1. 該類的所有實(shí)例都被回收了壹店。
  2. 加載該類的ClassLoader被回收了。
  3. 該類對(duì)應(yīng)的Class對(duì)象沒有被引用芝加,無法通過反射訪問到該類硅卢。

是否對(duì)類進(jìn)行回收還需要看參數(shù),HotSpot提供了-Xnoclassgc參數(shù)控制妖混。

在大量的使用反射老赤、動(dòng)態(tài)代理、CGLib等字節(jié)碼框架制市、動(dòng)態(tài)生成JSP抬旺、OSGi這類頻繁定義ClassLoader的場(chǎng)景都需要虛擬機(jī)具備類卸載的功能,以防止方法區(qū)溢出祥楣。

三开财、垃圾收集算法

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

步驟
  1. 標(biāo)記:標(biāo)記出需要回收的對(duì)象。
  2. 清除:統(tǒng)一回收所有被標(biāo)記的對(duì)象误褪。
問題
  1. 效率問題:標(biāo)記和清除的效率都不高责鳍。
  2. 空間碎片:標(biāo)記清除后會(huì)產(chǎn)生大量的空間碎片,可能導(dǎo)致之后無法分配連續(xù)的大空間而提前出發(fā)另一次垃圾收集動(dòng)作兽间。

2. 復(fù)制算法

步驟
  1. 將可用內(nèi)存劃分為大小相等的兩塊A历葛、B,每次只使用其中一塊嘀略,假設(shè)使用A恤溶。
  2. 當(dāng)A內(nèi)存用完了,就將A中存活的對(duì)象復(fù)制到B塊內(nèi)存上帜羊。
  3. 將A塊內(nèi)存一次性全部清理咒程。
  4. 再次分配時(shí)直接在B塊上偏移指針即可。

雖然解決了空間碎片的問題讼育,但是這種算法會(huì)使可用空間大大減小帐姻,每次只可用原空間的50%。

分塊的優(yōu)化

研究新生代中98%的對(duì)象都會(huì)被回收奶段,所以并不需要1:1分塊饥瓷。可將內(nèi)存分為一塊較大的Eden忧饭,和兩塊較小的Survivor扛伍。

  1. 每次使用Eden和一塊Survivor。
  2. 回收使將其中存活對(duì)象復(fù)制到另一塊Survivor中词裤。
  3. 最后清理掉Eden和之前的那塊Survivor內(nèi)存刺洒。


  • 優(yōu)點(diǎn):HotSpot默認(rèn)Eden和Survivor比例8:1鳖宾,可分配區(qū)域?yàn)樵笮〉?0%,所以每次分配時(shí)也就只有10%的空間浪費(fèi)逆航。
  • 缺點(diǎn):沒有辦法保證每次只有不多于10%大小的對(duì)象存活鼎文。當(dāng)存活對(duì)象10%時(shí),就會(huì)導(dǎo)致Survivor空間不足因俐,需要依賴其他內(nèi)存進(jìn)行分配擔(dān)保拇惋。

當(dāng)另一個(gè)Survivor沒有足夠空間存放上次回收的存活對(duì)象時(shí),這些對(duì)象就會(huì)直接通過分配擔(dān)保機(jī)制進(jìn)入老年代抹剩。

復(fù)制操作在存活率較高的情況下的效率很低撑帖,并且需要進(jìn)行分配擔(dān)保。所以老年代一般不會(huì)使用復(fù)制算法澳眷。

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

與標(biāo)記清除算法的前面部分一樣胡嘿,但是標(biāo)記整理算法不是在標(biāo)記后直接回收,而是讓所有存活對(duì)象向一端移動(dòng)钳踊,然后清理掉端邊界以外的內(nèi)容衷敌。


4. 分代收集思想

根據(jù)對(duì)象存活周期的不同,將內(nèi)存劃分幾塊拓瞪。一般分為新生代和老生代缴罗,根據(jù)不同的特點(diǎn)采用合適的算法。

新生代:復(fù)制算法祭埂。
老生代:標(biāo)記-清理或標(biāo)記-整理算法面氓。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛆橡,隨后出現(xiàn)的幾起案子侧但,更是在濱河造成了極大的恐慌,老刑警劉巖航罗,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異屁药,居然都是意外死亡粥血,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門酿箭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來复亏,“玉大人,你說我怎么就攤上這事缭嫡〉抻” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵妇蛀,是天一觀的道長耕突。 經(jīng)常有香客問我笤成,道長,這世上最難降的妖魔是什么眷茁? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任炕泳,我火速辦了婚禮,結(jié)果婚禮上上祈,老公的妹妹穿的比我還像新娘培遵。我一直安慰自己,他們只是感情好登刺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布籽腕。 她就那樣靜靜地躺著,像睡著了一般纸俭。 火紅的嫁衣襯著肌膚如雪皇耗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天掉蔬,我揣著相機(jī)與錄音廊宪,去河邊找鬼。 笑死女轿,一個(gè)胖子當(dāng)著我的面吹牛箭启,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛉迹,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼傅寡,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了北救?” 一聲冷哼從身側(cè)響起荐操,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珍策,沒想到半個(gè)月后托启,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡攘宙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年屯耸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹭劈。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疗绣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铺韧,到底是詐尸還是另有隱情多矮,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布哈打,位于F島的核電站塔逃,受9級(jí)特大地震影響讯壶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜患雏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一鹏溯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淹仑,春花似錦丙挽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吓肋,卻和暖如春凳怨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背是鬼。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國打工肤舞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人均蜜。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓李剖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親囤耳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子篙顺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

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