Java 內存回收算法

一挂捅、判斷Java中對象存活的算法

1馅扣、引用計數(shù)器算法:

Java 堆 中每個具體對象(不是引用)都有一個引用計數(shù)器脐恩。當一個對象被創(chuàng)建并初始化賦值后舍肠,該變量計數(shù)設置為1向族。每當有一個地方引用它時呵燕,計數(shù)器值就加1。當引用失效時件相,即一個對象的某個引用超過了生命周期(出作用域后)或者被設置為一個新值時再扭,計數(shù)器值就減1。任何引用計數(shù)為0的對象可以被當作垃圾收集夜矗。當一個對象被垃圾收集時泛范,它引用的任何對象計數(shù)減1。

  • 優(yōu)點:
    引用計數(shù)收集器執(zhí)行簡單紊撕,判定效率高罢荡,交織在程序運行中。對程序不被長時間打斷的實時環(huán)境比較有利。
  • 缺點:
    難以檢測出對象之間的循環(huán)引用(A對象引用B對象区赵,B對象又引用A對象惭缰,但是A,B對象已不被任何其他對象引用)笼才。同時从媚,引用計數(shù)器增加了程序執(zhí)行的開銷。所以在JDK1.1之后患整,這個算法已經(jīng)不再使用了拜效。
2、可達性分析算法

可達性分析算法也叫根搜索算法各谚,通過一系列的稱為 GC Roots 的對象作為起點紧憾,然后向下搜索。搜索所走過的路徑稱為引用鏈 (Reference Chain)昌渤, 當一個對象到 GC Roots沒有任何引用鏈相連時, 即該對象不可達赴穗,也就說明此對象是 不可用的。

Java中, 可作為GC Roots的對象包括以下四種:

  1. 虛擬機棧(棧幀中的本地變量表)中引用的對象
  2. 方法區(qū)中靜態(tài)引用指向的對象膀息。也就是類中的 static 修飾的變量所引用的對象
  3. 方法區(qū)常量引用的對象
  4. 本地方法棧JNINative方法)的引用的對象
  5. 仍處于存活狀態(tài)中的線程對象

如下圖所示: Object5般眉、Object6、Object7 雖然互有關聯(lián), 但它們到GC Roots是不可達的, 因此也會被判定為可回收的對象潜支。

二甸赃、對象引用分類

1. 強引用(Strong Reference)
在代碼中普遍存在的,類似Object obj = new Object()這類引用冗酿,只要強引用還在埠对,垃圾收集器永遠不會回收掉被引用的對象。

2. 軟引用(Sofe Reference)
有用但并非必需 的對象裁替,可用SoftReference類來實現(xiàn)軟引用项玛。在系統(tǒng)將要發(fā)生內存溢出異常之前,將會把這些對象列進回收范圍之中進行二次回收弱判。如果這次回收還沒有足夠的內存襟沮,才會拋出內存溢出異常。

3. 弱引用(Weak Reference)
非必需的對象昌腰,但它的強度比軟引用更弱开伏,被弱引用關聯(lián)的對象只能生存到下一次垃圾收集發(fā)生之前,JDK提供了WeakReference類來實現(xiàn)弱引用剥哑。無論當前內存是否足夠硅则,用軟引用相關聯(lián)的對象都會被回收掉淹父。

4. 虛引用(Phantom Reference)
虛引用也稱為幽靈引用或幻影引用株婴,是最弱的一種引用關系,JDK提供了PhantomReference類來實現(xiàn)虛引用。為一個對象設置虛引用的唯一目的是:能在這個對象在垃圾回收器回收時收到一個系統(tǒng)通知困介。

三大审、JVM 垃圾回收算法

1、標記-清除算法

標記-清除(Mark-Sweep)算法是現(xiàn)代垃圾回收算法的思想基礎座哩。標記-清除算法將垃圾回收分為兩個階段:標記階段和清除階段徒扶。一種可行的實現(xiàn)是,在標記階段根穷,首先通過根節(jié)點姜骡,標記所有從根節(jié)點開始的可達對象。因此屿良,未被標記的對象就是未被引用的垃圾對象(好多資料說標記出要回收的對象圈澈,其實明白大概意思就可以了)。然后尘惧,在清除階段康栈,清除所有未被標記的對象。

  • 優(yōu)點:
    實現(xiàn)簡單喷橙,不需要進行對象進行移動啥么。

  • 缺點:
    標記、清除過程效率低贰逾,產(chǎn)生大量不連續(xù)的內存碎片悬荣,提高了垃圾回收的頻率。

如圖:


2疙剑、標記整理算法

標記整理算法 采用和 標記-清除算法 一樣的方式進行對象的標記隅熙,但后續(xù)不直接對可回收對象進行清理,而是將所有的存活對象往一端空閑空間移動核芽,然后清理掉端邊界以外的內存空間囚戚。

  • 優(yōu)點:
    解決了標記-清理算法存在的內存碎片問題。
    沒有內存碎片后轧简,對象創(chuàng)建內存分配也更快速了(可以使用TLAB進行分配)驰坊。

  • 缺點:
    效率問題,(同標記清除算法)標記和整理兩個過程的效率都不高哮独;
    仍需要進行局部對象移動拳芙,一定程度上降低了效率。

如圖:

3皮璧、復制算法

復制算法可以解決效率問題舟扎,它將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊悴务,當這一塊內存用完了睹限,就將還存活著的對象復制到另一塊上面譬猫,然后再把已經(jīng)使用過的內存空間一次清理掉,這樣使得每次都是對整個半?yún)^(qū)進行內存回收羡疗,內存分配時也就不用考慮內存碎片等復雜情況染服,只要移動堆頂指針,按順序分配內存即可(還可使用TLAB進行高效分配內存)叨恨。

  • 優(yōu)點:
    效率高柳刮,沒有內存碎片(按順序分配內存即可,實現(xiàn)簡單痒钝、運行高效秉颗,不用考慮內存碎片。)
  • 缺點:
    可用的內存大小縮小為原來的一半送矩,對象存活率高時會頻繁進行復制站宗,效率將會變低。

如圖:

圖的上半部分是未回收前的內存區(qū)域益愈,圖的下半部分是回收后的內存區(qū)域梢灭。通過圖,我們發(fā)現(xiàn)不管回收前還是回收后都有一半的空間未被利用蒸其。

4敏释、分代收集算法

當前商業(yè)虛擬機都是采用分代收集算法,它根據(jù)對象存活周期的不同將內存劃分為幾塊摸袁,一般是把Java堆分為年輕代钥顽、老年代 和 永久代。然后根據(jù)各個年代的特點采用最適當?shù)氖占惴恐谛律蟹浯螅看卫占及l(fā)現(xiàn)有大批對象死去,只有少量存活蝶怔,就選用復制算法奶浦,而老年代因為對象存活率高,沒有額外空間對它進行分配擔保踢星,就必須使用“標記清理”或者“標記整理”算法來進行回收澳叉。

如圖:


圖的左半部分是未回收前的內存區(qū)域,右半部分是回收后的內存區(qū)域沐悦。

對象分配策略:

  1. 對象優(yōu)先在Eden區(qū)域分配成洗,如果對象過大直接分配到Old區(qū)域。
  2. 長時間存活的對象進入到Old區(qū)域藏否。

改進復制算法:
現(xiàn)在的商業(yè)虛擬機都采用這種收集算法來回收新生代瓶殃,IBM公司的專門研究表明,新生代中的對象98%是“朝生夕死”的副签,所以并不需要按照1:1的比例來劃分內存空間遥椿,而是將內存分為一塊較大的Eden空間和兩塊較小的Survivor空間基矮,每次使用Eden和其中一塊Survivor 。當回收時修壕,將Eden和Survivor中還存活著的對象一次性地復制到另外一塊Survivor空間上愈捅,最后清理掉Eden和剛才用過的Survivor空間遏考。
HotSpot 虛擬機默認Eden和Survivor的大小比例是8:1慈鸠,也就是每次新生代中可用內存空間為整個新生代容量的90%(80%+10%),只有10%的內存會被“浪費”灌具。當然青团,98%的對象可回收只是一般場景下的數(shù)據(jù),我們沒有辦法保證每次回收都只有不多于10%的對象存活咖楣,當Survivor空間不夠用時督笆,需要依賴其他內存(這里指老年代)進行分配擔保(Handle Promotion)。

年輕代诱贿、老年代 和 永久代娃肿,如下圖所示:

圖1
新生代(Young generation)

絕大多數(shù)最新被創(chuàng)建的對象會被分配到這里,由于大部分對象在創(chuàng)建后會很快變得不可達珠十,所以很多對象被創(chuàng)建在新生代料扰,然后消失。對象從這個區(qū)域消失的過程我們稱之為 minor GC焙蹭。

新生代 中存在一個Eden區(qū)和兩個Survivor區(qū)晒杈。新對象會首先分配在Eden中(如果新對象過大,會直接分配在老年代中)孔厉。在GC中拯钻,Eden中的對象會被移動到Survivor中,直至對象滿足一定的年紀(定義為熬過GC的次數(shù))撰豺,會被移動到老年代粪般。

可以設置新生代老年代的相對大小。這種方式的優(yōu)點是新生代大小會隨著整個大小動態(tài)擴展污桦。參數(shù) -XX:NewRatio 設置老年代新生代的比例刊驴。例如 -XX:NewRatio=8 指定 老年代/新生代8/1. 老年代占堆大小的 7/8新生代 占堆大小的 1/8(默認即是 1/8)寡润。
例如:

-XX:NewSize=64m -XX:MaxNewSize=1024m -XX:NewRatio=8
老年代(Old generation)

對象沒有變得不可達捆憎,并且從新生代中存活下來,會被拷貝到這里梭纹。其所占用的空間要比新生代多躲惰。也正由于其相對較大的空間,發(fā)生在老年代上的GC要比新生代要少得多变抽。對象從老年代中消失的過程础拨,可以稱之為major GC(或者full GC)氮块。

永久代(permanent generation)

像一些類的層級信息方法數(shù)據(jù)方法信息(如字節(jié)碼诡宗,變量大小)滔蝉,運行時常量池(JDK7之后移出永久代),已確定的符號引用虛方法表等等塔沃。它們幾乎都是靜態(tài)的并且很少被卸載和回收蝠引,在JDK8之前的HotSpot虛擬機中,類的這些永久的 數(shù)據(jù)存放在一個叫做永久代的區(qū)域蛀柴。

永久代一段連續(xù)的內存空間螃概,我們在JVM啟動之前可以通過設置-XX:MaxPermSize的值來控制永久代的大小。但是JDK8之后取消了永久代鸽疾,這些元數(shù)據(jù)被移到了一個與堆不相連的稱為元空間 (Metaspace) 的本地內存區(qū)域吊洼。

小結
JDK8堆內存一般是劃分為年輕代老年代不同年代 根據(jù)自身特性采用不同的垃圾收集算法制肮。

對于新生代冒窍,每次GC時都有大量的對象死亡,只有少量對象存活豺鼻∽垡海考慮到復制成本低,適合采用復制算法拘领。因此有了From SurvivorTo Survivor區(qū)域意乓。

對于老年代,因為對象存活率高约素,沒有額外的內存空間對它進行擔保届良。因而適合采用標記-清理算法標記-整理算法進行回收

參考:

JVM垃圾回收算法
JVM系列(五) - JVM垃圾回收算法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市圣猎,隨后出現(xiàn)的幾起案子士葫,更是在濱河造成了極大的恐慌,老刑警劉巖送悔,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慢显,死亡現(xiàn)場離奇詭異,居然都是意外死亡欠啤,警方通過查閱死者的電腦和手機荚藻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洁段,“玉大人应狱,你說我怎么就攤上這事§羲浚” “怎么了疾呻?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵除嘹,是天一觀的道長。 經(jīng)常有香客問我岸蜗,道長尉咕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任璃岳,我火速辦了婚禮年缎,結果婚禮上,老公的妹妹穿的比我還像新娘矾睦。我一直安慰自己晦款,他們只是感情好炎功,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布枚冗。 她就那樣靜靜地躺著,像睡著了一般蛇损。 火紅的嫁衣襯著肌膚如雪赁温。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天淤齐,我揣著相機與錄音股囊,去河邊找鬼。 笑死更啄,一個胖子當著我的面吹牛稚疹,可吹牛的內容都是我干的。 我是一名探鬼主播祭务,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼内狗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了义锥?” 一聲冷哼從身側響起柳沙,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拌倍,沒想到半個月后赂鲤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡柱恤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年数初,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梗顺。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡泡孩,死狀恐怖,靈堂內的尸體忽然破棺而出荚守,到底是詐尸還是另有隱情珍德,我是刑警寧澤练般,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站锈候,受9級特大地震影響薄料,放射性物質發(fā)生泄漏。R本人自食惡果不足惜泵琳,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一摄职、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧获列,春花似錦谷市、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巩梢,卻和暖如春创泄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背括蝠。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工鞠抑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忌警。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓搁拙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親法绵。 傳聞我的和親對象是個殘疾皇子箕速,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容