JVM 垃圾回收

JVM的垃圾回收主要針對(duì) “堆” 和 “方法區(qū)”,主要解決以下問(wèn)題:

  • 哪些內(nèi)存需要回收磺箕?(對(duì)象存活判定算法)
  • 觸發(fā)垃圾回收的條件奖慌?
  • 如何回收?(垃圾收集算法)
  • 用什么回收松靡?(垃圾收集器)

本文先介紹 對(duì)象存活判定算法简僧、垃圾收集算法,然后介紹常見(jiàn)的 JVM 垃圾收集器雕欺。

1. 對(duì)象存活判定算法

一般來(lái)說(shuō)岛马,判定對(duì)象是否可以被回收有許多算法,目前主流的算法有 引用計(jì)數(shù)法阅茶、可達(dá)性分析法蛛枚,本節(jié)對(duì)這兩種算法進(jìn)行簡(jiǎn)要介紹。

1.1 引用計(jì)數(shù)法

每個(gè)對(duì)象維護(hù)一個(gè)引用計(jì)數(shù)器脸哀。當(dāng)有一個(gè)新的引用指向該對(duì)象時(shí)蹦浦,引用計(jì)數(shù)器就+1;當(dāng)指向該引用對(duì)象失效時(shí)撞蜂,計(jì)數(shù)器就-1盲镶;當(dāng)引用計(jì)數(shù)器值為0時(shí),說(shuō)明該對(duì)象可以被回收蝌诡。

JVM 沒(méi)有選用 引用計(jì)數(shù)法 來(lái)管理內(nèi)存溉贿,其主要原因就是引用計(jì)數(shù)法很難解決對(duì)象之間的循環(huán)引用問(wèn)題
循環(huán)引用示例:

public class MyObject {
    public Object ref = null;
    public static void main(String[] args) {
        MyObject myObject1 = new MyObject();
        MyObject myObject2 = new MyObject();
        myObject1.ref = myObject2;
        myObject2.ref = myObject1;
        myObject1 = null;
        myObject2 = null;
    }
}

如上圖所示浦旱,白色框代表在堆中開(kāi)辟了一個(gè)內(nèi)存空間宇色,黃色和藍(lán)色線(xiàn)代表引用,各位兩條,也就代表計(jì)數(shù)器各為2宣蠕,myObject1 和 myObject2 分別指向 null例隆,線(xiàn)各自消失一條,計(jì)數(shù)器減1抢蚀,但還剩1镀层,也就如圖中ref的指向,沒(méi)有恢復(fù)0皿曲,所以不會(huì)被回收唱逢。

1.2 可達(dá)性分析法

目前主流的JVM都采用可達(dá)性分析算法來(lái)判定對(duì)象是否存活。

可達(dá)性分析法:通過(guò)"GC Roots"對(duì)象(必須活躍的引用)作為起點(diǎn)屋休,從起點(diǎn)開(kāi)始進(jìn)行圖的遍歷坞古,所走過(guò)的路徑稱(chēng)為引用鏈。當(dāng)一個(gè)對(duì)象不在引用鏈上時(shí)博投,則該對(duì)象被判定為可回收對(duì)象绸贡。

上圖 Object 5 盯蝴、6 毅哗、7 會(huì)被回收。

可以作為“GC Roots”的對(duì)象包括以下幾種:

  • 虛擬機(jī)棧 中引用的對(duì)象捧挺;
    比如正在運(yùn)行的線(xiàn)程的虛擬機(jī)棧上的引用變量虑绵。
  • 本地方法棧中JNI(Native方法)的引用的對(duì)象;
  • 方法區(qū)中的類(lèi)靜態(tài)屬性引用的對(duì)象闽烙;
  • 方法區(qū)中的常量引用的對(duì)象翅睛。

1.3 Java引用類(lèi)型
怎么樣的對(duì)象算沒(méi)有被引用?Java語(yǔ)言其實(shí)一共定義了4種引用黑竞,按強(qiáng)度從大到小依次是:

強(qiáng)引用(Strong Reference)
強(qiáng)引用是使用最普遍的引用捕发,GC永遠(yuǎn)不會(huì)回收被強(qiáng)引用的對(duì)象。
例:Object obj=new Object();

軟引用(Soft Reference)
軟引用的對(duì)象很魂,只有在內(nèi)存不足時(shí)扎酷,GC會(huì)對(duì)其回收。
也就是說(shuō)遏匆,只有發(fā)生 OOM 之前的 GC法挨,才會(huì)對(duì)軟引用的對(duì)象進(jìn)行回收
軟引用有時(shí)被用來(lái)實(shí)現(xiàn)內(nèi)存敏感的高速緩存。
例:

// 獲取對(duì)象并緩存
SoftReference softRef = new SoftReference(new SomeClass());

// 從軟引用中獲取對(duì)象
Object cache = softRef.get();
if (cache == null) {
    // 當(dāng)軟引用被回收后重新獲取對(duì)象
    cache = new SomeClass();
}
return (SomeClass)cache;

弱引用(Weak Reference)
弱引用的對(duì)象擁有更短暫的生命周期幅聘。弱引用與軟引用的區(qū)別在于:在GC進(jìn)行存活對(duì)象判定時(shí)凡纳,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否帝蒿,都會(huì)回收它荐糜。

Car car = new Car();
WeakReference<Car> weakCar = new WeakReference<Car>(car);

//假設(shè)此處進(jìn)行了一次GC
System.gc() 

 //打印true
System.out.println(weakCar.get()==null); 

虛引用(Phantom Reference)
虛引用是最弱的一種引用關(guān)系。

2. 垃圾回收觸發(fā)條件

由于對(duì)象進(jìn)行了分代處理,因此垃圾回收區(qū)域暴氏、時(shí)間也不一樣丛版。GC有兩種類(lèi)型:Scavenge GC和Full GC。對(duì)于一個(gè)擁有終結(jié)方法的對(duì)象偏序,在垃圾收集器釋放對(duì)象前必須執(zhí)行終結(jié)方法页畦。但是當(dāng)垃圾收集器第二次收集這個(gè)對(duì)象時(shí)便不會(huì)再次調(diào)用終結(jié)方法。

Minor GC

一般情況下研儒,當(dāng)新對(duì)象生成豫缨,并且在Eden申請(qǐng)空間失敗時(shí),就會(huì)觸發(fā)Minor GC端朵,對(duì)Eden區(qū)域進(jìn)行GC好芭,清除非存活對(duì)象,并且把尚且存活的對(duì)象移動(dòng)到Survivor區(qū)冲呢,然后整理Survivor的兩個(gè)區(qū)舍败。這種方式的GC是對(duì)新生代的Eden區(qū)進(jìn)行,不會(huì)影響到老年代敬拓。因?yàn)榇蟛糠謱?duì)象都是從Eden區(qū)開(kāi)始的邻薯,同時(shí)Eden區(qū)不會(huì)分配的很大,所以Eden區(qū)的GC會(huì)頻繁進(jìn)行乘凸。

Full GC

對(duì)整個(gè)堆進(jìn)行整理厕诡,包括年輕代、老年代 和 永久代营勤。Full GC因?yàn)樾枰獙?duì)整個(gè)對(duì)進(jìn)行回收灵嫌,所以比 Scavenge GC 要慢,因此應(yīng)該盡可能減少 Full GC的次數(shù)葛作。在對(duì)JVM調(diào)優(yōu)的過(guò)程中寿羞,很大一部分工作就是對(duì)于 Full GC 的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:

  • 老年代(Tenured)被寫(xiě)滿(mǎn)

  • 永久代(Perm)被寫(xiě)滿(mǎn)

  • System.gc() 被 顯示 調(diào)用

3. 垃圾收集算法

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

標(biāo)記-清除(Mark-Sweep)算法赂蠢,分為 標(biāo)記 和 清除 階段:首先標(biāo)記出所有需要回收的對(duì)象绪穆,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。

缺點(diǎn):

  1. 效率問(wèn)題客年;
    標(biāo)記和清除兩個(gè)過(guò)程的效率都不高
  2. 空間問(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)作司恳。

3.2 復(fù)制算法

復(fù)制(Copying)算法,將內(nèi)存分為相等的兩塊绍傲,每次只使用一塊扔傅。當(dāng)這塊內(nèi)存用光耍共,就將還存活的對(duì)象復(fù)制到另外一塊,然后再把已經(jīng)使用過(guò)的空間一次清理掉猎塞。

優(yōu)點(diǎn):內(nèi)存分配/清除的效率都很高试读,不用考慮內(nèi)存碎片等情況。
缺點(diǎn):內(nèi)存縮小為原來(lái)的一半荠耽,空間利用率低钩骇。

現(xiàn)代商用JVM一般采用復(fù)制算法來(lái)回收新生代,因?yàn)樾律写蟛糠謱?duì)象都是朝生夕死的铝量。實(shí)際一般按照8:1:1的比例將內(nèi)存空間劃分為一塊Eden區(qū)(80%)和兩塊Survivor區(qū)(各10%)倘屹。

3.3 標(biāo)記整理算法

標(biāo)記-整理(Mark-Compact)算法,標(biāo)記過(guò)程和標(biāo)記清除算法一樣慢叨,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理纽匙,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存拍谐。

現(xiàn)代商用JVM一般采用標(biāo)記-整理算法回收老年代烛缔。因?yàn)槔夏甏鷮?duì)象存活率高,一般只需要清除少量對(duì)象轩拨。

3.4 分代收集算法

目前大部分JVM都采用的分代收集(Generational Collection)算法践瓷。它的核心思想是根據(jù)對(duì)象存活的生命周期將內(nèi)存劃分為若干個(gè)不同的區(qū)域,不同區(qū)域采用不同的垃圾回收算法气嫁。

一般情況下將堆區(qū)劃分為老年代(Tenured Generation)当窗、新生代(Young Generation)、永久代寸宵。
新生代:對(duì)象朝生暮死,存活率低元咙,一般選用“復(fù)制算法”梯影;
老年代:對(duì)象存活率高、沒(méi)有額外空間對(duì)對(duì)象進(jìn)行分配擔(dān)保庶香,一般采用“標(biāo)記-整理”算法甲棍。

4、JVM垃圾收集器

收集器名稱(chēng) 介紹 使用時(shí)期 算法
Serial 單線(xiàn)程收集器赶掖,暫停所有線(xiàn)程 新生代 復(fù)制算法
Serial Old 單線(xiàn)程收集器感猛,暫停所有線(xiàn)程 老年代 標(biāo)記-整理算法
ParNew 多線(xiàn)程收集器,與用戶(hù)線(xiàn)程并發(fā) 新生代 復(fù)制算法
Parallel Scavenge 多線(xiàn)程收集器奢赂,與用戶(hù)線(xiàn)程并發(fā)陪白,可控制吞吐量 新生代 復(fù)制算法
Parallel Old 多線(xiàn)程收集器,與用戶(hù)線(xiàn)程并發(fā) 老年代 標(biāo)記-整理算法
CMS 多線(xiàn)程收集器膳灶,與用戶(hù)線(xiàn)程并發(fā)咱士;對(duì)CPU資源敏感立由;標(biāo)記階段,用戶(hù)線(xiàn)程依舊運(yùn)行 老年代 標(biāo)記-清除算法
G1 技術(shù)前沿成果序厉;空間整合锐膜;可預(yù)測(cè)停頓,消耗時(shí)間短 沒(méi)有限制 標(biāo)記-整理算法

參考

http://www.reibang.com/p/667e0d876666
http://www.reibang.com/p/3d9484f266ae

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弛房,一起剝皮案震驚了整個(gè)濱河市道盏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌文捶,老刑警劉巖捞奕,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拄轻,居然都是意外死亡颅围,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)恨搓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)院促,“玉大人,你說(shuō)我怎么就攤上這事斧抱〕M兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵辉浦,是天一觀的道長(zhǎng)弄抬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)宪郊,這世上最難降的妖魔是什么掂恕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮弛槐,結(jié)果婚禮上懊亡,老公的妹妹穿的比我還像新娘。我一直安慰自己乎串,他們只是感情好店枣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著叹誉,像睡著了一般鸯两。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钧唐,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天蕉斜,我揣著相機(jī)與錄音缀棍,去河邊找鬼。 笑死机错,一個(gè)胖子當(dāng)著我的面吹牛爬范,可吹牛的內(nèi)容都是我干的弱匪。 我是一名探鬼主播青瀑,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萧诫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斥难!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起帘饶,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎及刻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體暑劝,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颗搂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丢氢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卖丸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猜嘱,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布弦撩,位于F島的核電站论皆,受9級(jí)特大地震影響猾漫,放射性物質(zhì)發(fā)生泄漏感凤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一陪竿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闰挡,春花似錦礁哄、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)劳翰。三九已至馒疹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颖变,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工马胧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衔峰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓威彰,卻偏偏與公主長(zhǎng)得像穴肘,于是被迫代替她去往敵國(guó)和親歇盼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子评抚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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

  • 0. 前言 JVM筆記系列,以JDK1.7為基準(zhǔn)邢笙,主要以《深入理解Java虛擬機(jī)》(第二版)和《Java虛擬機(jī)規(guī)范...
    郭尋撫閱讀 907評(píng)論 0 3
  • 垃圾收集基礎(chǔ) Java 語(yǔ)言的一大特點(diǎn)就是可以進(jìn)行自動(dòng)垃圾回收處理鸣剪,而無(wú)需開(kāi)發(fā)人員過(guò)于關(guān)注系統(tǒng)資源,例如內(nèi)存資源的...
    Austin_Brant閱讀 744評(píng)論 0 2
  • 許多高級(jí)編程語(yǔ)言都帶有自動(dòng)垃圾回收特性债鸡,以將程序員從繁瑣復(fù)雜的內(nèi)存分配和釋放工作中解脫。本文將概述常見(jiàn)的垃圾回收算...
    kelgon閱讀 2,054評(píng)論 2 52
  • 注意 : 本系列文章為學(xué)習(xí)系列,部分內(nèi)容會(huì)取自相關(guān)書(shū)籍或者網(wǎng)絡(luò)資源,在文章中間和末尾處會(huì)有標(biāo)注 垃圾回收的意義 它...
    lyk2112閱讀 331評(píng)論 0 0
  • 近期熱播的《獵場(chǎng)》號(hào)稱(chēng)是本年度職場(chǎng)壓軸大劇,果然名不虛傳告唆。劇中的一號(hào)人物鄭秋冬(胡歌飾)有著雄才偉略,從尼泊爾淘金...
    彧瑛閱讀 978評(píng)論 1 6