【深入理解Java虛擬機(jī)讀書(shū)筆記】垃圾收集器與內(nèi)存分配策略

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

垃圾收集器主要回收的內(nèi)存區(qū)域是堆和方法區(qū)

判斷對(duì)象是否已死

  • 引用計(jì)數(shù)算法
    • 通過(guò)計(jì)算一個(gè)對(duì)象是否被其他對(duì)象所引用來(lái)判斷該對(duì)象是否可以被回收什湘,Java中不采用該方法贩据,存在循環(huán)引用問(wèn)題(a->b, b->a剔宪,此時(shí)a斗锭,b均不會(huì)被回收)
  • 可達(dá)性分析算法
    • 從一系列的GC Root出發(fā)胞得,如果一個(gè)對(duì)象沒(méi)有任何從引用鏈與GC Root相連接,則該對(duì)象可以被回收
    • Java中的GC Root對(duì)象
      • 虛擬機(jī)棧中本地變量表中引用的對(duì)象
      • 本地方法棧中JNI(也就是Native方法)引用的對(duì)象
      • 方法區(qū)中類(lèi)靜態(tài)變量引用的對(duì)象
      • 方法區(qū)中常量引用的對(duì)象
  • 引用類(lèi)型
    • 強(qiáng)引用,永遠(yuǎn)不會(huì)被回收
    • 軟引用骗炉,有用但不是必須的對(duì)象诗赌,在系統(tǒng)即將要發(fā)生內(nèi)存溢出異常之前,會(huì)對(duì)其進(jìn)行二次回收
    • 弱引用颓影,比軟應(yīng)用更弱,只能生存到下一次垃圾收集發(fā)生之前魏颓,垃圾收集器工作時(shí)驼壶,會(huì)回收
    • 虛引用,最弱的一種引用碟渺,無(wú)法通過(guò)虛引用來(lái)取得一個(gè)對(duì)象
  • 對(duì)象死亡過(guò)程
    • 兩次標(biāo)記
      • 如果對(duì)象在進(jìn)行可達(dá)性分析之后芜繁,發(fā)現(xiàn)沒(méi)有與GC Roots相連接的引用鏈,則會(huì)被第一次標(biāo)記并且執(zhí)行一次篩選高蜂,篩選的條件是此對(duì)象是否有必要執(zhí)行finalize()方法捺宗,當(dāng)對(duì)象沒(méi)有覆蓋finalize方法,或者finalize方法已經(jīng)被虛擬機(jī)調(diào)用過(guò)胶果,則將這兩種情況都視為沒(méi)有必要執(zhí)行
      • 如果對(duì)象有必要執(zhí)行finalize方法匾嘱,則對(duì)象會(huì)被放置在一個(gè)叫F-Queue的隊(duì)列中,并且在稍后由一個(gè)虛擬機(jī)自行建立早抠、低優(yōu)先級(jí)的Finalizer線(xiàn)程去執(zhí)行
      • finalize方法是對(duì)象逃脫死亡命運(yùn)的最后一次機(jī)會(huì)霎烙,稍后GC將對(duì)F-Queue中的對(duì)象進(jìn)行第二次小規(guī)模標(biāo)記,如果對(duì)象在finalize方法中成功拯救自己蕊连,也就是重新與引用鏈上的任意對(duì)象建立關(guān)聯(lián)悬垃,則在第二次標(biāo)記時(shí),它將被移出即將回收集合
  • 無(wú)用類(lèi)
    • 該類(lèi)的所有實(shí)例都被回收甘苍,也就是堆中不存在該類(lèi)的任何實(shí)例
    • 加載該類(lèi)的ClassLoader已經(jīng)被回收
    • 該類(lèi)對(duì)應(yīng)的Class對(duì)象沒(méi)有在任何地方唄引用尝蠕,無(wú)法在任何地方通過(guò)反射訪(fǎng)問(wèn)該類(lèi)

垃圾收集算法

  • 標(biāo)記-清除算法(Mark-Sweep)
    • 分為兩個(gè)階段,標(biāo)記载庭、清除
    • 缺點(diǎn)
      • 標(biāo)記以及清除過(guò)程的效率不高
      • 標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片看彼,導(dǎo)致無(wú)法為大對(duì)象分配空間,從而導(dǎo)致觸發(fā)另一次垃圾收集算法
  • 復(fù)制算法(Copying)
    • 將可用內(nèi)存按容量分為大小相等的兩塊囚聚,每次只使用其中一塊靖榕,當(dāng)這一塊使用完之后,就將還存活著的對(duì)象復(fù)制到另一塊內(nèi)存顽铸,然后一次性清理已使用過(guò)的內(nèi)存空間
    • 缺點(diǎn)
      • 導(dǎo)致每次可用內(nèi)存大小縮小為原來(lái)的一半
      • 在對(duì)象存活比較多時(shí)需要進(jìn)行比較多的復(fù)制操作
    • 現(xiàn)在商業(yè)虛擬機(jī)都采用這種收集算法來(lái)回收新生代(朝生夕死)茁计,將內(nèi)存分為較大的Eden空間和兩個(gè)較小的Survivor空間,每次使用Eden和其中一塊Survicor空間谓松,回收時(shí)星压,將存活對(duì)象復(fù)制到另一個(gè)Survicor空間践剂,最后清理Eden和剛剛使用過(guò)的Survicor空間,HotSpot中默認(rèn)Eden:Survivor = 8:1娜膘,也就是新生代中每次可用內(nèi)存為90%逊脯,當(dāng)Survivor空間不足時(shí),需要老年代進(jìn)行分配擔(dān)保
    • 當(dāng)另一塊Survivor空間不足以存放上一次新生代存活下來(lái)的對(duì)象時(shí)劲绪,通過(guò)分配擔(dān)保機(jī)制直接進(jìn)入老年代
  • 標(biāo)記-整理算法(Mark-Compact)
    • 分為兩個(gè)階段男窟,標(biāo)記、整理贾富,讓存活的對(duì)象向一端移動(dòng)歉眷,然后直接清除端邊界以外的內(nèi)存,主要用于老年代
  • 分代收集算法(Generation Collection)
    • 商業(yè)虛擬機(jī)主要采用方式颤枪,根據(jù)對(duì)象存活周期的不同汗捡,將內(nèi)存劃分為幾塊,一般把堆分為新生代和老年代畏纲,然后根據(jù)各個(gè)年代的特點(diǎn)扇住,采用最適當(dāng)?shù)氖占惴?/li>
    • 新生代中,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去盗胀,只有少量存活艘蹋,就選用復(fù)制算法
    • 老年代中,對(duì)象存活率高票灰,沒(méi)有額外的空間對(duì)它進(jìn)行分配擔(dān)保女阀,一般采用標(biāo)記清除或者標(biāo)記整理算法

HotSpot的算法實(shí)現(xiàn)

  • 程序在執(zhí)行時(shí),并非在所有的地方都能停頓下來(lái)開(kāi)始GC屑迂,只有在到達(dá)安全點(diǎn)時(shí)才暫停
  • 安全點(diǎn)的選定基本上是以程序"是否具有讓程序長(zhǎng)時(shí)間執(zhí)行的特征"為標(biāo)準(zhǔn)進(jìn)行選定的浸策,長(zhǎng)時(shí)間特征為,指令序列的復(fù)用惹盼,如方法調(diào)用庸汗,循環(huán)跳轉(zhuǎn),異常跳轉(zhuǎn)等手报,只有具有這些功能的指令才會(huì)產(chǎn)生安全點(diǎn)
  • 讓線(xiàn)程在安全點(diǎn)上停頓的方法
    • 搶先式中斷
      • GC發(fā)生時(shí)蚯舱,把所有線(xiàn)程全部中斷,如果發(fā)現(xiàn)線(xiàn)程中斷的地方不在安全點(diǎn)上掩蛤,就恢復(fù)線(xiàn)程晓淀,讓其運(yùn)行至安全點(diǎn),幾乎沒(méi)有虛擬機(jī)采用這種方式
    • 主動(dòng)式中斷
      • 當(dāng)GC需要中斷線(xiàn)程時(shí)盏档,僅僅簡(jiǎn)單地設(shè)置一個(gè)標(biāo)志,各個(gè)線(xiàn)程在執(zhí)行時(shí)主動(dòng)地輪詢(xún)?cè)摌?biāo)志燥爷,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)就自己中斷掛起蜈亩,輪詢(xún)中斷的地方和安全點(diǎn)是重合的
  • 安全區(qū)域
    • 在一段代碼片段中懦窘,引用關(guān)系不會(huì)發(fā)生變化,這個(gè)區(qū)域中的任意地方開(kāi)始GC都是安全的
    • 線(xiàn)程執(zhí)行到安全區(qū)域時(shí)稚配,首先標(biāo)志自己已經(jīng)進(jìn)入安全區(qū)域畅涂,此時(shí),當(dāng)JVM發(fā)起GC時(shí)道川,就不需要管將自己標(biāo)志為安全區(qū)域的線(xiàn)程了午衰,線(xiàn)程要離開(kāi)安全區(qū)域時(shí),先檢查系統(tǒng)是否完成了根節(jié)點(diǎn)枚舉(或者整個(gè)GC過(guò)程)冒萄,如果完成臊岸,則繼續(xù)離開(kāi),否則尊流,等待到可以安全離開(kāi)安全區(qū)域的信號(hào)為止

垃圾收集器

  • Serial收集器
    • 單線(xiàn)程收集器帅戒,在進(jìn)行垃圾收集時(shí),必須暫停所有的工作現(xiàn)場(chǎng)崖技,直到收集結(jié)束
    • 新生代采用復(fù)制算法逻住,老年代采用標(biāo)記-整理算法
    • 虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)新生代收集器
    • 簡(jiǎn)單,高效
  • ParNew收集器
    • Serial收集器的多線(xiàn)程版本迎献,使用多線(xiàn)程進(jìn)行垃圾收集瞎访,其余基本同Serial
    • 新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法
    • 運(yùn)行在Server模式下首選的新生代收集器吁恍,除了Serial外扒秸,只有ParNew能與CMS收集器配合工作
  • Parallel Scavenge收集器
    • 并行的采用復(fù)制算法的新生代收集器
    • 目標(biāo)是達(dá)到一個(gè)可控制的吞吐量,吞吐量?jī)?yōu)先收集器
  • Serial Old收集器
    • Serial收集器的老年代版本践盼,單線(xiàn)程鸦采,使用標(biāo)記-整理算法
    • 主要給Client模式下的虛擬機(jī)使用
  • Parallel Old收集器
    • 多線(xiàn)程,采用標(biāo)記整理算法
    • 注重吞吐量以及CPU資源敏感的場(chǎng)合
  • CMS收集器
    • CMS(Concurrent Mark Sweep)以獲得最短回收停頓時(shí)間為目標(biāo)
    • 采用標(biāo)記-清除算法
    • 運(yùn)行過(guò)程
      1. 初始標(biāo)記咕幻,需要Stop The World渔伯,僅僅標(biāo)記GC Roots能直接關(guān)聯(lián)到的對(duì)象,速度快
      2. 并發(fā)標(biāo)記肄程,對(duì)GC Roots Trancing的過(guò)程
      3. 重新標(biāo)記锣吼,需要Stop The World,修正并發(fā)標(biāo)記期間因?yàn)橛脩?hù)程序停止運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分標(biāo)記記錄蓝厌,比初始化標(biāo)記時(shí)間長(zhǎng)玄叠,但比并發(fā)標(biāo)記時(shí)間短
      4. 并發(fā)清除
    • 并發(fā)標(biāo)記以及并發(fā)清除過(guò)程可以與用戶(hù)線(xiàn)程一起并發(fā)執(zhí)行
    • 缺點(diǎn)
      • 對(duì)CPU資源非常敏感,一定數(shù)量的線(xiàn)程用戶(hù)回收拓提,從而使得用戶(hù)線(xiàn)程數(shù)量比例降低
      • 無(wú)法處理浮動(dòng)垃圾读恃,可能出現(xiàn)Concurrent Mode Failure失敗而導(dǎo)致另一次Full GC的產(chǎn)生
        • 浮動(dòng)垃圾:在并發(fā)標(biāo)記過(guò)程中,由于標(biāo)記線(xiàn)程與用戶(hù)線(xiàn)程共同運(yùn)行,所以可能給還會(huì)產(chǎn)生新的垃圾寺惫,而這些垃圾在本次手機(jī)過(guò)程無(wú)法被回收
      • 由于是基于標(biāo)記-清除算法疹吃,會(huì)產(chǎn)生許多的內(nèi)存碎片,當(dāng)碎片過(guò)多時(shí)西雀,會(huì)給大對(duì)象分配帶來(lái)麻煩萨驶,從而觸發(fā)一次Full GC,內(nèi)存整理過(guò)程無(wú)法并發(fā)艇肴,所以會(huì)導(dǎo)致停頓時(shí)間變長(zhǎng)
  • G1收集器
    • Garbage-First收集器腔呜,面向服務(wù)器端應(yīng)用的垃圾收集器,主要同于替換CMS收集器
    • 特點(diǎn)
      • 并行與并發(fā)
        • 充分利用多CPU再悼,多核環(huán)境核畴,使用多個(gè)CPU來(lái)縮短Stop-The-World停頓的時(shí)間
      • 分代收集
      • 空間整合
        • 整體采用標(biāo)記-整理算法實(shí)現(xiàn),局部采用復(fù)制算法
      • 可預(yù)測(cè)的停頓
        • 除了降低停頓外帮哈,還能建立可預(yù)測(cè)的停頓時(shí)間模型
        • 可以有計(jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集膛檀,跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大小(回收獲得的空間以及回收所需要的經(jīng)驗(yàn)值),在后臺(tái)維護(hù)一個(gè)優(yōu)先隊(duì)列娘侍,每次根據(jù)允許的收集時(shí)間咖刃,優(yōu)先回收價(jià)值最大的Region,保證在有限時(shí)間內(nèi)可以獲得盡可能高的收集效率
    • 內(nèi)存布局
      • 將整個(gè)Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域Region憾筏,雖然保留新生代嚎杨,老年代的概念,但是新生代氧腰,老年代不再是物理隔離枫浙,都是一部分Region的集合

內(nèi)存分配

對(duì)象的內(nèi)存分配,主要是在堆上進(jìn)行分配古拴,也有可能經(jīng)過(guò)JIT編譯之后被拆散為標(biāo)量并間接在棧上分配箩帚,對(duì)象主要分配在新生代的Eden區(qū),如果啟動(dòng)了本地線(xiàn)程分配緩存(LTAB)黄痪,則按照線(xiàn)程優(yōu)先在TLAB上分配紧帕,少數(shù)情況下也直接在老年代中分配

普遍的內(nèi)存分配策略

  • 對(duì)象優(yōu)先在Eden分配,如果空間不夠桅打,將觸發(fā)一次Minor GC
  • 大對(duì)象直接進(jìn)入老年區(qū)
  • 長(zhǎng)期存活的對(duì)象將直接進(jìn)入老年代
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末是嗜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挺尾,更是在濱河造成了極大的恐慌鹅搪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遭铺,死亡現(xiàn)場(chǎng)離奇詭異丽柿,居然都是意外死亡恢准,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)甫题,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)顷歌,“玉大人,你說(shuō)我怎么就攤上這事幔睬。” “怎么了芹扭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵麻顶,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我舱卡,道長(zhǎng)辅肾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任轮锥,我火速辦了婚禮矫钓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舍杜。我一直安慰自己新娜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布既绩。 她就那樣靜靜地躺著概龄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饲握。 梳的紋絲不亂的頭發(fā)上私杜,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音救欧,去河邊找鬼衰粹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛笆怠,可吹牛的內(nèi)容都是我干的铝耻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼骑疆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼田篇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起箍铭,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤泊柬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后诈火,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體兽赁,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡状答,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刀崖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惊科。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖亮钦,靈堂內(nèi)的尸體忽然破棺而出馆截,到底是詐尸還是另有隱情,我是刑警寧澤蜂莉,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布蜡娶,位于F島的核電站,受9級(jí)特大地震影響映穗,放射性物質(zhì)發(fā)生泄漏窖张。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一蚁滋、第九天 我趴在偏房一處隱蔽的房頂上張望宿接。 院中可真熱鬧,春花似錦辕录、人聲如沸睦霎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)碎赢。三九已至,卻和暖如春速梗,著一層夾襖步出監(jiān)牢的瞬間肮塞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工姻锁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枕赵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓位隶,卻偏偏與公主長(zhǎng)得像拷窜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涧黄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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