coolfiry

          認(rèn)認(rèn)真真做人,兢兢業(yè)業(yè)做事!
          posts - 39, comments - 17, trackbacks - 0, articles - 0

          垃圾收集機(jī)制(Garbage Collection)批判

          Posted on 2007-10-12 10:43 Coolfiry 閱讀(656) 評論(1)  編輯  收藏 所屬分類: Java

          在Java版發(fā)表這篇文章,似乎有點(diǎn)把矛頭指向Java了。其實(shí)不是,GC是所有新一代語言共有的特征,
          Python, Eiffel,C#,Roby等無一例外地都使用了GC機(jī)制。但既然Java中的GC最為著名,所以天塌
          下來自然應(yīng)該抗著。

          這篇短文源于comp.lang.java.programmer跟comp.lang.c++上發(fā)生的一場大辯論,支持C++和Java
          的兩派不同勢力展開了新世紀(jì)第一場沖突,跟貼發(fā)言超過350,兩派都有名角壓陣。C++陣營的擂主是
          Pete Becker,ACM會員,Dinkumware Ltd. 的技術(shù)副總監(jiān)。此君精通C++和Java,開發(fā)過兩種語言的
          核心類庫,但是卻對C++狂熱之極,而對于Java頗不以為然。平時談到Java的時候還好,一旦有人膽
          敢用Java來批判C++,立刻忍不住火爆脾氣跳將出來,以堅(jiān)韌不拔的毅力和大無畏精神與對手周旋,
          舌戰(zhàn)群儒,哪怕只剩下一個人也要血戰(zhàn)到底。這等奇人當(dāng)真少見!我真奇怪他整天泡在usenet上,
          不用工作么?他的老板P.J. Plauger如此寬宏大量?Java陣營主角是一個網(wǎng)名Razzi的兄弟,另外有
          Sun公司大名鼎鼎的Peter van der Linden助陣,妙語連珠,寸土必爭,加上人多勢眾,一度占據(jù)優(yōu)勢。
          C++陣營里大拿雖然很多,但是大多數(shù)沒有Pete那么多閑工夫,例如Greg Comeau,Comeau公司老板,
          每次來個只言片語,實(shí)在幫不了Pete多大忙。但是自從C++陣營中冒出一個無名小子,網(wǎng)名Courage(勇氣),
          發(fā)動對Java GC機(jī)制的批判,形勢為之一變。C++陣營眼下處于全攻之勢,Java陣營疲于防守,只能
          招架說:“你們沒有證據(jù),沒有統(tǒng)計(jì)資料”,形勢很被動。

          垃圾收集(GC)不是一直被Java fans用來炫耀,引以為傲的優(yōu)點(diǎn)么?怎么成了弱點(diǎn)了?我大惑不解,定睛
          一看,才覺得此中頗有道理。

          首先,Java Swing庫存在大量資源泄漏問題,這一點(diǎn)SUN非常清楚,稱之為bugs,正在極力修正。但是看來
          這里的問題恐怕不僅是庫編寫者的疏忽,可能根源在于深層的機(jī)制,未必能夠輕易解決,搞不好要傷筋動骨。
          不過這個問題不是那么根本,C++陣營覺得如果抓住對方的弱點(diǎn)攻擊,就算是占了上風(fēng)也沒什么說服力。誰
          沒有缺點(diǎn)呢?于是反其道而行之,猛烈攻擊Java陣營覺得最得意的東西,Java的GC機(jī)制本身。

          首先來想一想,memory leak到底意味著什么。在C++中,new出來的對象沒有delete,這就導(dǎo)致了memory
          leak。但是C++早就有了克服這一問題的辦法——smart pointer。通過使用標(biāo)準(zhǔn)庫里設(shè)計(jì)精致的auto_ptr
          以及各種STL容器,還有例如boost庫(差不多是個準(zhǔn)標(biāo)準(zhǔn)庫了)中的四個smart pointers,C++
          程序員只要
          花上一個星期的時間學(xué)習(xí)最新的資料,就可以拍著胸脯說:“我寫的
          程序沒有memory leak!”。

          相比之下,Java似乎更優(yōu)秀,因?yàn)閺囊婚_始你就不用考慮什么特殊的機(jī)制,大膽地往前new,自有GC替你
          收拾殘局。Java的GC實(shí)際上是
          JVM中的一個獨(dú)立線程,采用不同的算法策略來收集heap中那些不再有
          reference指向的垃圾對象所占用的內(nèi)存。但是,通常情況下,GC線程的優(yōu)先級比較低,只有在當(dāng)前
          程序
          空閑的時候才會被調(diào)度,收集垃圾。當(dāng)然,如果JVM感到內(nèi)存緊張了,JVM會主動調(diào)用GC來收集垃圾,獲取
          更多的內(nèi)存。請注意,Java的GC工作的時機(jī)是:1. 當(dāng)前
          程序不忙,有空閑時間。2. 空閑內(nèi)存不足。
          現(xiàn)在我們考慮一種常見的情況,
          程序在緊張運(yùn)行之中,沒喲空閑時間給GC來運(yùn)行,同時機(jī)器內(nèi)存很大,
          JVM也沒有感到內(nèi)存不足,結(jié)果是什么?對了,GC形同虛設(shè),得不到調(diào)用。于是,內(nèi)存被不斷吞噬,而那些
          早已經(jīng)用不著的垃圾對象仍在在寶貴的內(nèi)存里睡大覺。例如:

          class BadGc {

              public void job1() {
                  String garbage = "I am a garbage, and just sleeping in your precious memory, " +
                            "how do you think you can deal with me? Daydreaming! HAHA!!!";
                  ....
              }

              public void job2() {...}

              ...
              ...

              public void job1000() {...}

              public static void main(String[] args) {
                  bgc = new BadGc();
           bgc.job1();
           bgc.job2();
           ...
           bgc.job1000();
              }
          }

          運(yùn)行中,雖然garbage對象在離開job1()之后,就再也沒有用了。但是因?yàn)?/span>程序忙,內(nèi)存還夠用,所以GC得
          不到調(diào)度,garbage始終不會被回收,直到
          程序運(yùn)行到bgc.job1000()時還躺在內(nèi)存里嘲笑你。沒轍吧!

          好了,我承認(rèn)這段程序很傻。但是你不要以為這只是理論上的假設(shè),恰恰相反,大多數(shù)實(shí)用中的Java程序都有
          類似的效應(yīng)。這就是為什么Java
          程序狂耗內(nèi)存,而且好像給它多少內(nèi)存吃都不夠。你花上大筆的銀子把內(nèi)存
          從128升到256,再升到512,結(jié)果是,一旦執(zhí)行復(fù)雜任務(wù),內(nèi)存還是被輕易填滿,而且多出來的這些內(nèi)存只是
          用來裝垃圾,GC還是不給面子地千呼萬喚不出來。等到你的內(nèi)存終于心力交瘁,GC才姍姍來遲,收拾殘局。而
          且GC工作的方式也很不好評價,一種方法是一旦有機(jī)會回收內(nèi)存,就把所有的垃圾都回收。你可以想象,這要
          花很長時間(幾百M(fèi)的垃圾??!),如果你這時侯正在壓下開炮的按鈕,GC卻叫了暫定,好了,你等死吧!另一
          種方法,得到機(jī)會之后,回收一些內(nèi)存,讓JVM感到內(nèi)存不那么緊張時就收手。結(jié)果呢,內(nèi)存里始終有大批垃
          圾,
          程序始終在半死不活的蕩著。最后,GC可以每隔一段時間就運(yùn)行一次,每次只回收一部分垃圾,這是現(xiàn)在
          大部分JVM的方式,結(jié)果是內(nèi)存也浪費(fèi)了,還動不動暫停幾百毫秒。難??!

          反過來看看C++利用smart pointer達(dá)成的效果,一旦某對象不再被引用,系統(tǒng)刻不容緩,立刻回收內(nèi)存。這
          通常發(fā)生在關(guān)鍵任務(wù)完成后的清理(cleanup)時期,不會影響關(guān)鍵任務(wù)的實(shí)時性,同時,內(nèi)存里所有的對象
          都是有用的,絕對沒有垃圾空占內(nèi)存。怎么樣?傳統(tǒng)、樸素的C++是不是更勝一籌?

          據(jù)統(tǒng)計(jì),目前的Java程序運(yùn)行期間占用的內(nèi)存通常為對應(yīng)C++程序的4-20倍。除了其它的原因,上面所說的是一個
          非常主要的因素。我們對memory leak如此憤恨,不就是因?yàn)樗鼘?dǎo)致大量的內(nèi)存垃圾得不到清除嗎?如果有了
          GC之后,垃圾比以前還來勢洶洶,那么GC又有什么好處呢?

          當(dāng)然,C++的smart pointer現(xiàn)在會使用的人不多,所以現(xiàn)在的C++程序普遍存在更嚴(yán)重的memory leak問題。
          但是,如果我奶奶跟舒馬赫比賽車輸?shù)袅耍隳軌蚵裨鼓禽v車子么?
          http://www.594k.com/java/html/y2007m1/12051/

          Feedback

          # re: 垃圾收集機(jī)制(Garbage Collection)批判  回復(fù)  更多評論   

          2007-10-17 16:47 by guest
          GC的目的不是沒有垃圾,而是不要讓垃圾造成系統(tǒng)崩潰
          所以JAVA的GC目的已經(jīng)達(dá)到了

          另外無論如何都不可能沒有垃圾的
          主站蜘蛛池模板: 洛浦县| 安义县| 巫山县| 屯门区| 银川市| 加查县| 乐平市| 岐山县| 五常市| 新郑市| 仙桃市| 渭南市| 嫩江县| 枣庄市| 黔江区| 张家界市| 新竹县| 满洲里市| 大庆市| 西丰县| 多伦县| 瓮安县| 百色市| 松阳县| 潍坊市| 石河子市| 织金县| 湖南省| 梅州市| 额敏县| 镇远县| 文化| 荆门市| 县级市| 呼和浩特市| 新和县| 乌恰县| 长治县| 博野县| 呼伦贝尔市| 河池市|