簡談垃圾回收機(jī)制

簡談垃圾回收機(jī)制

什么是垃圾回收機(jī)制查库?

垃圾是堆中 unreferenced objects, 就是沒有被變量引用的變量路媚。

什么是堆?

這里就要講到程序的堆棧樊销。這個(gè)東西與數(shù)據(jù)結(jié)構(gòu)里面的堆棧有所區(qū)別整慎。

首先來講什么是棧∥唬現(xiàn)在考慮下面這種情況裤园。

void bar(int a){
    printf("%d",a );
}

void foo(){
    int a = 0;
    bar(a);
}
int main(){
    foo();
    reutrn 0;
}

請問 CPU 是如何執(zhí)行這里的程序呢?由于CPU只能一條一條的執(zhí)行指令剂府,當(dāng) bar 結(jié)束時(shí)拧揽,我們?nèi)绾文軌蛑老乱粭l指令應(yīng)該執(zhí)行什么呢?其中一個(gè)想法時(shí),用 CPU 的一個(gè)寄存器保存之前 caller 的下一條命令的地址淤袜,當(dāng) bar 結(jié)束后繼續(xù)執(zhí)行就可以了痒谴。但是如果是有許多層的調(diào)用,顯然CPU的寄存器就不夠使用了铡羡。這里棧就應(yīng)運(yùn)而生了积蔚。最簡單的一個(gè)例子是,如何將遞歸調(diào)用的程序改為非遞歸的烦周。這里就是用到了 stack 這個(gè)數(shù)據(jù)結(jié)構(gòu)尽爆。在程序運(yùn)行中也一樣當(dāng)程序發(fā)生調(diào)用時(shí)。會(huì)1读慎、將 caller 的下一個(gè)指令的地址壓棧漱贱。2、將 called 函數(shù)的參數(shù)從右向左壓棧贪壳。3饱亿、將 called 函數(shù)的局部變量在棧中分配存儲(chǔ)空間蚜退。函數(shù)結(jié)束時(shí)再將這些東西出棧闰靴。

這里就有了一個(gè)問題,如果 called 程序猿手動(dòng)的分配了一個(gè)內(nèi)存空間钻注,將之中傳給 caller 函數(shù)指針可以對(duì)這些內(nèi)存空間進(jìn)行訪問蚂且。如下。那么這個(gè)分配的內(nèi)存空間是放在哪里呢幅恋?如果放在 stack 中杏死,當(dāng)函數(shù)返回時(shí),這個(gè)內(nèi)存空間就被彈出了捆交。

int *  bar(int a){
    int *p = malloc(a);
    printf("%d",a );
    return p;
}

void foo(){
    int a = 1000;
    int *p =  bar(a);
    free(p);
}
int main(){
    foo();
    reutrn 0;
}

為了解決這個(gè)問題淑翼,就出現(xiàn)了堆這種東西。這個(gè)與數(shù)據(jù)結(jié)構(gòu)中的堆有所區(qū)別品追。

堆區(qū)(heap) — 一般由程序員分配釋放玄括, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收肉瓦。

上例中的 malloc 出來的空間就是放在堆里面的遭京。一般來說 new 出來的對(duì)象或者內(nèi)存空間都是放在堆里面的。

更詳細(xì)的東西可以參考:C函數(shù)調(diào)用過程原理及函數(shù)棧幀分析

什么是 Garbage泞莉?

Student ali= new Student();
Student khalid= new Student(); 
ali=khalid;

此時(shí) ali 已經(jīng)沒有被引用了哪雕。所以你沒有辦法再訪問這個(gè)內(nèi)存空間。為了防止過多這樣無法訪問的內(nèi)存空間的出現(xiàn)鲫趁,就需要通過垃圾回收的機(jī)制來回收內(nèi)存斯嚎。在 C/C++ 中需要程序員手動(dòng)回收內(nèi)存。而在 Java 中 Java 虛擬機(jī)幫助我們完成這個(gè)事情。

什么是 GC

gc 是 Garbage Collection 的簡稱孝扛,是指找到垃圾列吼,并且回收分配給它的內(nèi)存。

什么時(shí)候會(huì)觸發(fā)GC苦始?

當(dāng)分配給程序的內(nèi)存會(huì)超過一定的門限時(shí)會(huì)觸發(fā)GC

程序會(huì)受到GC的影響么寞钥?

會(huì)的,當(dāng)GC時(shí)陌选,程序會(huì)掛起理郑。

GC的方式

1 引用計(jì)數(shù) Reference counting

這個(gè)概念和操作系統(tǒng)中的 page 從 內(nèi)存中換出,以及 hard link 刪除文件等等都是用到引用計(jì)數(shù)的概念咨油。當(dāng)被分配的內(nèi)存空間被引用時(shí)您炉,refcount++, 當(dāng)解除引用時(shí) refCount—役电。當(dāng)refCount = 0 時(shí)這個(gè)內(nèi)存空間便是垃圾赚爵。

python 就是用的 引用計(jì)數(shù)法。這種GC機(jī)制的好處就是簡單法瑟,但是會(huì)有一個(gè)問題冀膝,即循環(huán)引用的問題。

image

如圖所示霎挟,由于循環(huán)引用的存在窝剖,這些內(nèi)存空間在進(jìn)程結(jié)束之前是沒有辦法被回收的。并且這種方式會(huì)造成 heap 的碎片化酥夭。

2 第二種方式 mark-and-sweep 的方式

這種方式分為兩個(gè)步驟

2.1 Mark phase

GC 從 root node 遍歷引用的圖赐纱。什么是 GC roots 呢? 作為GC Roots的節(jié)點(diǎn)主要在全局性的引用執(zhí)行上下文中熬北。從這些 roots node 開始遍歷 heap 中的對(duì)象疙描,可以訪問的標(biāo)記 1.

2.2 Sweep phase

GC 回收heap中沒有被標(biāo)記 1 的空間。

這種方式的好處是

  • 避免了循環(huán)引用
  • 對(duì)對(duì)象的引用關(guān)系沒有修改

壞處處是

  • GC 過程中必須 掛起程序讶隐,因?yàn)楸闅v的過程如果 reference graph 改變起胰,會(huì)出現(xiàn)不一致情況。
  • 造成碎片化整份。

解決碎片化的問題

3 Stop-and-Copy Garbage Collection

將內(nèi)存分為兩部分待错,在 sweep 階段將 mark 的對(duì)象copy 到另一半內(nèi)存中。

4 增量收集器

增量收集器把堆棧分為多個(gè)域烈评,每次僅從一個(gè)域收集垃圾火俄。這會(huì)造成較小的應(yīng)用程序中斷。

如果 mutator 在 collector 遍歷某對(duì)象后將其釋放(floating garbage)讲冠,那么這個(gè)對(duì)象在本次 GC 不會(huì)被回收瓜客,但在下一輪 GC 開始時(shí)會(huì)被回收。

但是增量 GC 可能會(huì)有問題。

image

Incremental Update

如果改變某個(gè)指針的地址谱仪,那么之前的地址會(huì)被加入一 marking stack玻熙,便于后面再次檢查,這樣就可以保證在 GC 時(shí)疯攒,所有的對(duì)象都會(huì)被遍歷到嗦随,即使指向它們的指針發(fā)生了改變。

Incremental Copying

當(dāng) mutator 訪問到 fromspace 中的對(duì)象時(shí)敬尺,立刻將之拷貝到 topspace 中枚尼。這個(gè) copy-on-demand 使用 read-barrier 來保證。什么是讀屏障呢砂吞?讀屏障就是訪問每一個(gè)對(duì)象都是通過每個(gè)對(duì)象的 redirection pointer 來進(jìn)行訪問對(duì)象署恍。這樣通過對(duì)這個(gè)指針的狀態(tài)的設(shè)置可以保證訪問的是GC copy 后面的新地址,比如當(dāng)對(duì)象正被GC移動(dòng)蜻直,指針上的顏色就會(huì)不對(duì)盯质,這個(gè)屏障就會(huì)先把指針更新為有效地址再返回

JAVA 中的GC方式

分代算法:新生代使用復(fù)制算法,老生帶使用標(biāo)記清除算法或者標(biāo)記壓縮算法概而。幾乎所有的垃圾回收期都區(qū)分新生代和老生帶呼巷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市到腥,隨后出現(xiàn)的幾起案子朵逝,更是在濱河造成了極大的恐慌蔚袍,老刑警劉巖乡范,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異啤咽,居然都是意外死亡晋辆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門宇整,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓶佳,“玉大人,你說我怎么就攤上這事鳞青“运牵” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵臂拓,是天一觀的道長厚脉。 經(jīng)常有香客問我,道長胶惰,這世上最難降的妖魔是什么傻工? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上中捆,老公的妹妹穿的比我還像新娘鸯匹。我一直安慰自己,他們只是感情好泄伪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布殴蓬。 她就那樣靜靜地躺著,像睡著了一般蟋滴。 火紅的嫁衣襯著肌膚如雪科雳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天脓杉,我揣著相機(jī)與錄音糟秘,去河邊找鬼。 笑死球散,一個(gè)胖子當(dāng)著我的面吹牛尿赚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蕉堰,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凌净,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屋讶?” 一聲冷哼從身側(cè)響起冰寻,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎皿渗,沒想到半個(gè)月后斩芭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乐疆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年划乖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挤土。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琴庵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仰美,到底是詐尸還是另有隱情迷殿,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布咖杂,位于F島的核電站庆寺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏翰苫。R本人自食惡果不足惜止邮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一这橙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧导披,春花似錦屈扎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至止毕,卻和暖如春模蜡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扁凛。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工忍疾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谨朝。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓卤妒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親字币。 傳聞我的和親對(duì)象是個(gè)殘疾皇子则披,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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

  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,203評(píng)論 0 7
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū))洗出,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評(píng)論 0 7
  • JVM筆記 JDK:Java士复、JVM、Java API類庫翩活,是支持java程序開發(fā)的最小環(huán)境阱洪。JRE:Java A...
    一條小袍袍YoY閱讀 879評(píng)論 0 4
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,164評(píng)論 0 2
  • 概念1:內(nèi)存自動(dòng)管理,1、提高了軟件開發(fā)的抽象度隅茎;2澄峰、程序員可以將精力集中在實(shí)際的問題上而不用分心來管理內(nèi)存的問題...
    諸子百家誰的天下閱讀 1,776評(píng)論 2 1