為什么程序員要學(xué)GC

今天跟大家分享一下《垃圾回收的算法與實(shí)現(xiàn)》,這本書一出版即進(jìn)入IT圖書銷量榜前列,由此可見大家對(duì)探秘GC的渴望。

再不學(xué)GC就老了,快來看看為什么GC讓程序員心動(dòng)!

什么是GC?

GC 是 Garbage Collection 的簡稱,中文稱為“垃圾回收”。在現(xiàn)實(shí)世界中,“垃圾”指的是那些不讀的書、不穿的衣服等不用的東西。在 GC 中,“垃圾”的定義也是如此,GC 把程序不用的內(nèi)存空間視為垃圾。

GC 要做兩件事。

找到內(nèi)存空間里的垃圾;

回收垃圾,讓程序員能再次利用這部分空間。

滿足這兩項(xiàng)功能的程序就是 GC。那么GC 到底會(huì)給程序員帶來怎樣的好處呢?

沒有GC的世界

在沒有 GC 的世界里,程序員必須自己手動(dòng)進(jìn)行內(nèi)存管理,必須清楚地確保必要的內(nèi)存空間,釋放不要的內(nèi)存空間。

程序員在手動(dòng)進(jìn)行內(nèi)存管理時(shí),申請(qǐng)內(nèi)存尚不存在什么問題,但在釋放不要的內(nèi)存空間時(shí),就必須一個(gè)不漏地釋放。這非常地麻煩。如果忘記釋放內(nèi)存空間,該內(nèi)存空間就會(huì)發(fā)生內(nèi)存泄露,即無法被使用,但它又會(huì)持續(xù)存在下去。如果將發(fā)生內(nèi)存泄露的程序放著不管,總有一刻內(nèi)存會(huì)被占滿,甚至還可能導(dǎo)致系統(tǒng)崩潰。

另外,在釋放內(nèi)存空間時(shí),如果忘記初始化指向釋放對(duì)象的內(nèi)存空間的指針,這個(gè)指針就會(huì)一直指向釋放完畢的內(nèi)存空間。因?yàn)檫@個(gè)指針沒有指向有效的內(nèi)存空間,處于一種懸掛的狀態(tài),所以我們稱其為“懸垂指針”(dangling pointer)。如果在程序中錯(cuò)誤地引用了懸垂指針,就會(huì)產(chǎn)生無法預(yù)期的BUG。此外,懸垂指針也會(huì)導(dǎo)致嚴(yán)重的安全漏洞(2009 年 IE6/7 的零日漏洞曾轟動(dòng)一時(shí)。——丁靈注) 。

更有甚者,還可能會(huì)出現(xiàn)錯(cuò)誤釋放了使用中的內(nèi)存空間的情況。一旦錯(cuò)誤釋放了使用中的內(nèi)存空間,下一次程序使用此空間時(shí)就會(huì)發(fā)生故障。大多數(shù)情況下會(huì)發(fā)生段錯(cuò)誤,運(yùn)氣不好的話還可能引發(fā)惡性 BUG。

上述這樣與內(nèi)存相關(guān)的 BUG,其共通之處在于“難以確定 BUG 的原因”。我們都知道,與內(nèi)存相關(guān)的 BUG 的潛在場所和 BUG 出現(xiàn)的場所在位置上(或者是時(shí)間上)不一致,所以很難確定 BUG 的原因。

有GC的世界

為了省去上述手動(dòng)內(nèi)存管理的麻煩,人們鉆研開發(fā)出了 GC。如果把內(nèi)存管理交給計(jì)算機(jī),程序員就不用去想著釋放內(nèi)存了。在手動(dòng)內(nèi)存管理中,程序員要判斷哪些是不用的內(nèi)存空間(垃圾),留意內(nèi)存空間的壽命。但只要有 GC 在,這一切都可以交給 GC 來做。

有了 GC,程序員就不用再去擔(dān)心因?yàn)橥酸尫艃?nèi)存等而導(dǎo)致 BUG,從而大大減輕了負(fù)擔(dān)。也不用再去頭疼費(fèi)事的內(nèi)存管理。GC 能讓程序員告別惱人的內(nèi)存管理,把精力集中在更本質(zhì)的編程工作上。

GC的歷史

GC 是一門古老的技術(shù)

據(jù)筆者所知,GC 因?yàn)?Java 的發(fā)布而一舉成名,所以很多人可能會(huì)認(rèn)為 GC 是最近才有的技術(shù)。不過 GC 有著非常久遠(yuǎn)的歷史,最初的 GC 算法是 John McCarthy 在 1960 年發(fā)布的。

John McCarthy 身為 Lisp 之父和人工智能之父,是一名非常有名的黑客,事實(shí)上他同時(shí)也是 GC 之父。1960年,McCarthy 在其論文中首次發(fā)布了 GC 算法。當(dāng)然,當(dāng)時(shí)還沒有 Garbage Collection這個(gè)詞。在這篇論文中發(fā)布的算法,就是現(xiàn)在我們所說的 GC 標(biāo)記 - 清除算法。

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

1960 年,George E. Collins 在論文中發(fā)布了稱為引用計(jì)數(shù)的 GC 算法。當(dāng)時(shí) Collins 可能沒有注意到,引用計(jì)數(shù)法有個(gè)缺點(diǎn),就是它不能回收“循環(huán)引用”。Harold McBeth在 1963 年指出了這個(gè)缺點(diǎn)。

GC 復(fù)制算法

1963 年,也有“人工智能之父”之稱的 Marvin L. Minsky 在論文中發(fā)布了復(fù)制算法。GC 復(fù)制算法把內(nèi)存分成了兩部分,這篇論文中將第二部分稱為磁帶存儲(chǔ)空間——不得不說帶有濃烈的時(shí)代色彩。

50 年來,GC 的根本都沒有改變

從 50 年前 GC 算法首次發(fā)布以來,眾多研究者對(duì)其進(jìn)行了各種各樣的研究,因此許多 GC 算法也得以發(fā)布。但事實(shí)上,這些算法只不過是把前文中提到的三種算法進(jìn)行組合或應(yīng)用。也可以這么說,1963 年 GC 復(fù)制算法誕生時(shí),GC 的根本性內(nèi)容就已經(jīng)完成了。

未知的第四種算法

現(xiàn)在為世人所知的 GC 算法,不過是從之前介紹的三種基本算法中衍生出來的產(chǎn)物。

本書中除了細(xì)致介紹這些基本的 GC 算法,還會(huì)介紹應(yīng)用到它們的 GC 算法。把這些算法全看完后,請(qǐng)跟筆者一起,就 GC 的課題進(jìn)行思考。也許發(fā)現(xiàn)全新的第四種基本算法的人,就是你。

為什么我們現(xiàn)在要學(xué)GC

有以下幾個(gè)原因。

1、GC—— 存在即合理

現(xiàn)在我們使用的多數(shù)編程語言都搭載有 GC。以下是幾個(gè)具體的例子。

Lisp

Java

Ruby

Python

Perl

Haskell

大家有沒有用過其中的某種編程語言?如果用過,那你在不知不覺中獲得了 GC 帶來的好處。

對(duì)編程語言來說,GC 就是一個(gè)無名英雄,默默地做著貢獻(xiàn)。打個(gè)比方,天鵝在水面優(yōu)雅地游動(dòng)時(shí),實(shí)際上腳蹼?yún)s在水下拼命地劃水。GC 也是如此。在由編程語言構(gòu)造的美麗的源代碼這片水下,GC 在拼命地將垃圾回收再利用。

如上所述,GC 是語言處理程序中非常重要的一部分,相當(dāng)于樹蔭。應(yīng)該有很多人感覺“GC 幫忙回收垃圾是理所當(dāng)然”的吧?

GC 基本上是高負(fù)載處理,需要花費(fèi)一定的時(shí)間。打個(gè)比方,當(dāng)編寫像動(dòng)作游戲這樣追求即時(shí)性的程序時(shí),就必須盡量壓低 GC 導(dǎo)致的最大暫停時(shí)間。如果因?yàn)?GC 導(dǎo)致玩家頻繁卡頓,相信誰都會(huì)想摔手柄。碰到這種應(yīng)用,我們就需要選擇最大暫停時(shí)間較短的 GC 算法了。

再打個(gè)比方,對(duì)音樂和動(dòng)畫這樣類似于編碼應(yīng)用的程序來說,GC 的最大暫停時(shí)間就不那么重要了。更為重要的是,我們必須選擇一個(gè)整體處理時(shí)間更短的算法。

筆者深信,事先知道“這個(gè) GC 算法有這樣的特征,所以它適合這個(gè)應(yīng)用”對(duì)程序員來說很有價(jià)值。

2、多種多樣的處理程序的實(shí)現(xiàn)

近年來,隨著編程語言的發(fā)展,燃起了一股發(fā)布語言處理程序的勢(shì)頭,這些語言處理程序都搭載有不同的 GC 算法。作為語言處理程序的關(guān)鍵功能,很多人將采用了優(yōu)秀的 GC 算法作為一大賣點(diǎn)。

GC 性能在語言處理程序的性能評(píng)價(jià)中也是一大要素。為了正確評(píng)價(jià) GC 的性能,對(duì) GC 算法的理解是不可或缺的。

3、留意內(nèi)存空間的用法

應(yīng)該有不少人是通過使用搭載 GC 的編程語言來學(xué)習(xí)編程的吧。本書的作者之一中村也是如此,他最初接觸的編程語言是 Java??梢哉f在用Java 語言編寫程序時(shí)完全不用留意內(nèi)存空間的用法。當(dāng)然這也是多虧了GC,這是好事,但太不留心也會(huì)招致麻煩。例如,有時(shí)會(huì)出現(xiàn)無意中把內(nèi)存空間揮霍一空的情況,比如在循環(huán)中生成一些沒用的對(duì)象等。這是因?yàn)闆]有把握好編程語言背后的內(nèi)存管理的概念。

本書中以具體的編程語言為例,來說明編程語言中所使用的內(nèi)存空間的結(jié)構(gòu),以及 GC 的運(yùn)行。通過閱讀,我們就能在編程中留意內(nèi)存空間的用法了。

4、不會(huì)過時(shí)的技術(shù)

GC 自 1960 年發(fā)布以來,一直在吸引著頂尖工程師的目光。筆者確信,只要計(jì)算機(jī)構(gòu)造不發(fā)生根本性的改變,GC 就是一門不會(huì)過時(shí)的技術(shù)。對(duì)程序員來說,比起學(xué)習(xí)日新月異的新技術(shù),學(xué)習(xí) GC 這樣的古典技術(shù)不是更幸福嗎?

5、更何況,GC 很有趣

說實(shí)話,其實(shí)筆者自己學(xué)習(xí) GC 的時(shí)候,并沒有想過上述這些略復(fù)雜的事情,只是純粹覺得有趣。現(xiàn)在回過頭覺得學(xué)了 GC 真好,也只是因?yàn)樗邆淝懊婺切﹥?yōu)點(diǎn)。

筆者小時(shí)候就喜歡拆點(diǎn)什么東西,看看里面是怎樣的。電視機(jī)、收音機(jī)、紅白機(jī)什么的都拆了個(gè)遍。筆者至今都還記得看到其內(nèi)部時(shí)的快感,以及了解其構(gòu)造時(shí)的感動(dòng)。或許學(xué)習(xí) GC 也差不多是這樣。對(duì)筆者來說,研究 GC 這種理所當(dāng)然存在的東西,看看它的內(nèi)部是一件非常刺激的事。

6、讀者對(duì)象

本書由兩部分構(gòu)成。

算法篇

實(shí)現(xiàn)篇

在“算法篇”中,我們沒有必要去詳細(xì)了解特定的編程語言,你只要能用任何一種語言編程,就能往下讀“算法篇”。

閱讀“實(shí)現(xiàn)篇”需要具備 C 和 C++ 的知識(shí)。只要會(huì)用 C 的函數(shù)指針、C++ 的模板,閱讀“實(shí)現(xiàn)篇”就沒有什么障礙。關(guān)于 GC 算法的知識(shí),讀完本書的“算法篇”就相當(dāng)夠用了。

“實(shí)現(xiàn)篇”中涉及各種編程語言{ Python / Java / Ruby / JavaScript },最好有一定程度的了解,那樣閱讀起來會(huì)比較輕松。

垃圾回收的算法與實(shí)現(xiàn)

ガベージコレクションのアルゴリズムと実裝

作者:中村成洋 相川光

譯者:丁靈

定價(jià):99(各大網(wǎng)店可購買)

電子書:49.99(點(diǎn)擊目錄購買電子書)

Ruby之父松本行弘推薦,日本天才程序員兼LISP黑客竹內(nèi)郁雄審校

254幅圖解,輕松掌握GC經(jīng)典算法

實(shí)際源碼剖析,深入探討GC具體實(shí)現(xiàn)

本書分為“算法篇”和“實(shí)現(xiàn)篇”兩大部分。算法篇介紹了標(biāo)記–清除算法、引用計(jì)數(shù)法、復(fù)制算法、標(biāo)記–壓縮算法、保守式GC、分代垃圾回收、增量式垃圾回收、RCImmix算法等幾種重要的算法;實(shí)現(xiàn)篇介紹了垃圾回收在Python、DalvikVM、Rubinius、V8等幾種語言處理程序中的具體實(shí)現(xiàn)。適合各領(lǐng)域程序員閱讀。

目錄及試讀:

目錄

學(xué)習(xí) GC 之前

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

購買鏈接:

京東

當(dāng)當(dāng)

亞馬遜

互動(dòng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡欲明心閱讀 90,386評(píng)論 17 311
  • 一. 垃圾回收的意義 在C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)...
    Stan_Z閱讀 2,057評(píng)論 0 25
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,852評(píng)論 0 7
  • 1. 垃圾回收的意義在C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)象;而在...
    愛情小傻蛋閱讀 1,020評(píng)論 0 11
  • 經(jīng)常會(huì)聽到有人(也包括我)抱怨:這不是我要的生活 但是問問這些人,那你想要什么樣的生活 他腦子里能出現(xiàn)的就是:"此...
    侯開心的手帳閱讀 501評(píng)論 0 1

友情鏈接更多精彩內(nèi)容