關於垃圾回收被誤解的7件事

對Java垃圾回收最大的誤解是什麼?它實際又是什麼樣的呢?

當我仍是小孩的時候,父母常說若是你很差好學習,就只能去掃大街了。但他們不知道的是,清理垃圾其實是很棒的一件事。可能這也是即便在Java的世界中, 一樣有不少開發者對GC算法產生誤解的緣由——包括它們怎樣工做、GC是如何影響程序運行和你能對它作些什麼。所以咱們找到了Java性能調優專家Haim Yadid,並把名爲Java performance tuning guide的文章發表在Takipi的博客上。html

最新博文:關於垃圾回收被誤解的7件事
http://t.co/3QJLJuKCRqpic.twitter.com/aqQEF0zTkK
— Takipi (@takipid) April 6, 2015java

帶着對性能調優指南濃厚的興趣,咱們決定在這篇後續的博文中收集一些關於垃圾回收的流行觀點,而且指出爲何它們徹底是錯誤的。算法

來看看前7名:服務器

1. 只有一個垃圾回收器

不,而且4也是錯誤的答案。HotSpot JVM一共有4個垃圾回收器:Serial, Parallel / Throughput. CMS, and the new kid on the block G1。別急,另外還有一些非標準的垃圾回收器和更大膽的實現,好比Shenandoah或者其餘JVM使用的回收器(C4——Azul開發的無停頓回收器)。HotSpot默認使用Parallel / Throughput回收器,但它經常不是你運行程序的最佳選擇。好比CMS和G1會使GC停頓(GC pause)發生的頻率下降,可是對於每次停頓所花費的時間,極可能比Parallel回收器更長。另外一方面來講,在使用相同大小堆內存的狀況 下,Parallel回收器能帶來更高的吞吐量。多線程

結論:根據你的需求(可接受的GC停頓頻率和持續時間)選擇合適的垃圾回收器。架構

2. 並行(Parallel) = 併發(Concurrent)

一個GC週期(Garbage Collection cycle)能夠以STW(Stop-The-World)的形式出現,這會發生一次GC停頓,也能夠併發地執行從而無需暫停應用程序。更進一步來說,GC算法自己能夠是串行的(單線程),也能夠是並行的(多線程)。所以當咱們提到併發的GC時,並不表明它是並行完成的,相反當提到串行GC時,也並不意味着就必定會出現GC停頓。在GC的世界中,併發和並行是兩個徹底不一樣的概念。併發針對的是GC週期,而並行針對GC算法自身。併發

結論:垃圾回收的過程實際上有兩步,啓動GC週期和GC自身運行,這是不一樣的兩件事。ide

3. G1能解決全部問題

通過一系列修正和改進,Java 7中引入了G1回收器,它是JVM垃圾回收器中最新的組件。G1最大的優點就是解決了CMS中常見的內存碎片問題:GC週期會從老年代(Old Generation)中釋放內存塊,結果內存變得像瑞士奶酪那樣千瘡百孔,直到JVM對其無從下手了,纔不得不停下來處理這些碎片。可是故事沒這麼簡單,某些狀況下其餘回收器可能比G1有更好的表現,這徹底取決於你的需求。post

結論:沒有一個奇蹟般的回收器能解決全部GC問題,你應該經過具體實驗來選擇合適的回收器。性能

4. 平均事務時間是最須要被關注的指標

如 果你僅僅監控服務器的平均事務時間,那麼極可能錯過一些異常值。這些異常的狀況可能對用戶來講是毀滅性的,而人們沒有意識到它的重要性。好比一個事務在正 常狀況下耗時100ms,但受到GC停頓的影響,花了1分鐘才完成。除了用戶沒人會注意到這個問題,由於你只觀察了平均事務時間。試想有1%或者更多的用 戶經歷了這個場景,若是隻關注平均值,它就太容易被忽略了。想了解更多和延遲相關的問題和怎樣正確處理,能夠在這裏閱讀Gil Tene的博客。

結論:留心那些異常值,你能夠知道系統最後那1%的情況。(可不是這個1%

5. 下降新對象的分配率能夠改善GC的運行情況

咱們能夠 粗略地把系統中的對象分爲三種:長命(long-lived)對象,對它們咱們通常作不了什麼;中等壽命(mid-lived)對象,最大的問題可能出如今這短命(short-lived)對象,它們的釋放和回收一般都很快,在下個GC週期來臨時就會消失專一於中等壽命對象的分配率能夠帶來有益的結果,這對短命和長命的對象卻不是那麼有效。另外,控制中等壽命對象每每是一項困難的工做。

結論:給服務器帶來壓力的並不單純是對象的分配率,在運行過程當中這些對象的種類纔是一切麻煩的根源。

6. 調優能夠解決全部事

若是你的程序須要保存大量被頻繁修改的狀態,對JVM堆內存進行調優就沒法帶來很好的收益。較長的GC停頓是不可避免的。一個解決辦法是對架構進行改善,保證一個對響應時間有決定性影響或者形成瓶頸的過程當中,不包含大量狀態。大量狀態和響應能力是難以良好共存的,所以將它們分開處理才 是上上之選。

結論:不是全部的問題均可以經過調整JVM參數解決,有時你只須要回顧本身的繪圖板。(譯註:從新審視程序的設計)

7. GC日誌會致使巨大的系統開銷

簡單來講,這是錯的,尤爲在默認的日誌配置下。日誌數據是極爲有價值的,Java 7中還引入了鉤子來控制它們的大小,保證硬盤空間不被用盡。若是不收集GC日誌,那麼你會失去這幾乎是惟一的,知曉JVM垃圾回收器在生產環境中工做狀態 的方法。通常可接受的GC開銷以5%做爲上限,若是你能知道系統爲GC停頓付出的代價,也能對最小化這個代價採起行動,這種程度的開銷是不值一提的。

結論:在能力範圍內,儘量多地獲取系統在生產環境中的運行數據,你會發現那是一個全新的世界。

總結

但願上面的結論能幫助大家更好地把握Java垃圾回收器的工做。在大家的程序中出現過相似問題嗎?大家周圍還有沒有其餘對GC常見的誤解?請在下面的評論區留言。

原文連接: javacodegeeks 翻譯: ImportNew.com - 蔣 生武
譯文連接: http://www.importnew.com/15796.html

相關文章
相關標籤/搜索