国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
成為JavaGC專家Part I — 深入淺出Java垃圾回收機(jī)制

英文原文:cubrid,編譯:ImportNew- 王曉杰

對(duì)于Java開發(fā)人員來說,了解垃圾回收機(jī)制(GC)有哪些好處呢?首先可以滿足作為一名軟件工程師的求知欲,其次,深入了解GC如何工作可以幫你寫出更好的Java應(yīng)用。

這僅僅代表我個(gè)人的意見,但我堅(jiān)信一個(gè)精通GC的人往往是一個(gè)好的Java開發(fā)者。如果你對(duì)GC的處理過程感興趣,說明你已經(jīng)具備較大規(guī)模應(yīng)用的開發(fā)經(jīng)驗(yàn)。如果你曾經(jīng)想過如何正確的選擇GC算法,那意味著你已經(jīng)完全理解你所開發(fā)的應(yīng)用的特點(diǎn)。當(dāng)然,我們不能以偏概全,這不能作為評(píng)價(jià)一個(gè)好的開發(fā)人員的共通標(biāo)準(zhǔn)。但是,我要說的是,深入理解GC是成為一名偉大的程序員的必經(jīng)之路。

這是成為JavaGC專家系列文章的第一篇,本篇主要針對(duì)GC機(jī)制進(jìn)行介紹,在下一篇中,我們將重點(diǎn)探討分析GC狀態(tài)以及來自NHN的GC調(diào)優(yōu)的例子。

本文的目的是以一種簡(jiǎn)單的方式向你介紹GC機(jī)制。我希望這些文章能夠幫到你。實(shí)際上,我的學(xué)生已經(jīng)在Twitter上發(fā)布了一些很好的關(guān)于Java內(nèi)核的文章,并且大受歡迎。有興趣的話,你也可以關(guān)注他們。

回到正題,咱們繼續(xù)談垃圾回收,在學(xué)習(xí)GC之前,你首先應(yīng)該記住一個(gè)單詞:“stop-the-world”。Stop-the-world會(huì)在任何一種GC算法中發(fā)生。Stop-the-world意味著 JVM 因?yàn)橐獔?zhí)行GC而停止了應(yīng)用程序的執(zhí)行。當(dāng)Stop-the-world發(fā)生時(shí),除了GC所需的線程以外,所有線程都處于等待狀態(tài),直到GC任務(wù)完成。GC優(yōu)化很多時(shí)候就是指減少Stop-the-world發(fā)生的時(shí)間。

按代的垃圾回收機(jī)制

在Java程序中不能顯式地分配和注銷內(nèi)存。有些人把相關(guān)的對(duì)象設(shè)置為null或者調(diào)用System.gc()來試圖顯式地清理內(nèi)存。設(shè)置為null至少?zèng)]什么壞處,但是調(diào)用System.gc()會(huì)顯著地影響系統(tǒng)性能,必須徹底杜絕(還好,我還沒有見到NHN的哪個(gè)開發(fā)者調(diào)用這個(gè)方法)。

在Java中,開發(fā)人員無法直接在程序代碼中清理內(nèi)存,而是由垃圾回收器自動(dòng)尋找不必要的垃圾對(duì)象,并且清理掉他們。垃圾回收器會(huì)在下面兩種假設(shè)(hypotheses)成立的情況下被創(chuàng)建(稱之為假設(shè)不如改為推測(cè)(suppositions)或者前提(preconditions))。

  • 大多數(shù)對(duì)象會(huì)很快變得不可達(dá)

  • 只有很少的由老對(duì)象(創(chuàng)建時(shí)間較長(zhǎng)的對(duì)象)指向新生對(duì)象的引用

這些假設(shè)我們稱之為弱年代假設(shè)weak generational hypothesis)。為了強(qiáng)化這一假設(shè),HotSpot虛擬機(jī)將其物理上劃分為兩個(gè)–新生代(young generation)和老年代(old generation)。
新生代(Young generation): 絕大多數(shù)最新被創(chuàng)建的對(duì)象會(huì)被分配到這里,由于大部分對(duì)象在創(chuàng)建后會(huì)很快變得不可到達(dá),所以很多對(duì)象被創(chuàng)建在新生代,然后消失。對(duì)象從這個(gè)區(qū)域消失的過程我們稱之為”minor GC“。

老年代(Old generation): 對(duì)象沒有變得不可達(dá),并且從新生代中存活下來,會(huì)被拷貝到這里。其所占用的空間要比新生代多。也正由于其相對(duì)較大的空間,發(fā)生在老年代上的GC要比新生代少得多。對(duì)象從老年代中消失的過程,我們稱之為”major GC“(或者”full GC“)

請(qǐng)看下面這個(gè)圖表。

 圖1 : GC 空間 & 數(shù)據(jù)流

上圖中的持久代( permanent generation )也被稱為方法區(qū)method area)。他用來保存類常量以及字符串常量。因此,這個(gè)區(qū)域不是用來永久的存儲(chǔ)那些從老年代存活下來的對(duì)象。這個(gè)區(qū)域也可能發(fā)生GC。并且發(fā)生在這個(gè)區(qū)域上的GC事件也會(huì)被算為major GC。

有些人可能會(huì)問:
如果老年代的對(duì)象需要引用一個(gè)新生代的對(duì)象,會(huì)發(fā)生什么呢?
為了解決這個(gè)問題,老年代中存在一個(gè)”card table“,他是一個(gè)512 byte大小的塊。所有老年代的對(duì)象指向新生代對(duì)象的引用都會(huì)被記錄在這個(gè)表中。當(dāng)針對(duì)新生代執(zhí)行GC的時(shí)候,只需要查詢card table來決定是否可以被收集,而不用查詢整個(gè)老年代。這個(gè)card table由一個(gè)write barrier來管理。write barrier給GC帶來了很大的性能提升,雖然由此可能帶來一些開銷,但GC的整體時(shí)間被顯著的減少。

圖 2: Card Table 結(jié)構(gòu)

 新生代的構(gòu)成

為了更好地理解GC,我們現(xiàn)在來學(xué)習(xí)新生代,新生代是用來保存那些第一次被創(chuàng)建的對(duì)象,他可以被分為三個(gè)空間

  •  一個(gè)伊甸園空間(Eden

  •  兩個(gè)幸存者空間(Survivor

一共有三個(gè)空間,其中包含兩個(gè)幸存者空間。每個(gè)空間的執(zhí)行順序如下:

  1. 絕大多數(shù)剛剛被創(chuàng)建的對(duì)象會(huì)存放在伊甸園空間。

  2. 在伊甸園空間執(zhí)行了第一次GC之后,存活的對(duì)象被移動(dòng)到其中一個(gè)幸存者空間。

  3.   此后,在伊甸園空間執(zhí)行GC之后,存活的對(duì)象會(huì)被堆積在同一個(gè)幸存者空間。

  4.  當(dāng)一個(gè)幸存者空間飽和,還在存活的對(duì)象會(huì)被移動(dòng)到另一個(gè)幸存者空間。之后會(huì)清空已經(jīng)飽和的那個(gè)幸存者空間。

  5. 在以上的步驟中重復(fù)幾次依然存活的對(duì)象,就會(huì)被移動(dòng)到老年代。

如果你仔細(xì)觀察這些步驟就會(huì)發(fā)現(xiàn),其中一個(gè)幸存者空間必須保持是空的。如果兩個(gè)幸存者空間都有數(shù)據(jù),或者兩個(gè)空間都是空的,那一定標(biāo)志著你的系統(tǒng)出現(xiàn)了某種錯(cuò)誤。
通過頻繁的minor GC將數(shù)據(jù)移動(dòng)到老年代的過程可以用下圖來描述:

圖 3: GC執(zhí)行前后對(duì)比

需要注意的是HotSpot虛擬機(jī)使用了兩種技術(shù)來加快內(nèi)存分配。他們分別是是”bump-the-pointer“和“TLABs(Thread-Local Allocation Buffers)”。

Bump-the-pointer技術(shù)跟蹤在伊甸園空間創(chuàng)建的最后一個(gè)對(duì)象。這個(gè)對(duì)象會(huì)被放在伊甸園空間的頂部。如果之后再需要?jiǎng)?chuàng)建對(duì)象,只需要檢查伊甸園空間是否有足夠的剩余空間。如果有足夠的空間,對(duì)象就會(huì)被創(chuàng)建在伊甸園空間,并且被放置在頂部。這樣以來,每次創(chuàng)建新的對(duì)象時(shí),只需要檢查最后被創(chuàng)建的對(duì)象。這將極大地加快內(nèi)存分配速度。但是,如果我們?cè)诙嗑€程的情況下,事情將截然不同。如果想要以線程安全的方式以多線程在伊甸園空間存儲(chǔ)對(duì)象,不可避免的需要加鎖,而這將極大地的影響性能。TLABs 是HotSpot虛擬機(jī)針對(duì)這一問題的解決方案。該方案為每一個(gè)線程在伊甸園空間分配一塊獨(dú)享的空間,這樣每個(gè)線程只訪問他們自己的TLAB空間,再與bump-the-pointer技術(shù)結(jié)合可以在不加鎖的情況下分配內(nèi)存。
以上是針對(duì)新生代空間GC技術(shù)的簡(jiǎn)要介紹,你不需要刻意記住我剛剛提到的兩種技術(shù)。不知道他們不會(huì)對(duì)你產(chǎn)生什么影響,但是請(qǐng)務(wù)必記住在對(duì)象剛剛被創(chuàng)建之后,是保存在伊甸園空間的。那些長(zhǎng)期存活的對(duì)象會(huì)經(jīng)由幸存者空間轉(zhuǎn)存在老年代空間。

老年代GC處理機(jī)制

老年代空間的GC事件基本上是在空間已滿時(shí)發(fā)生,執(zhí)行的過程根據(jù)GC類型不同而不同,因此,了解不同的GC類型將有助于你理解本節(jié)的內(nèi)容。
JDK7一共有5種GC類型:

  1. Serial GC

  2. Parallel GC

  3. Parallel Old GC (Parallel Compacting GC)

  4. Concurrent Mark & Sweep GC  (or “CMS”)

  5. Garbage First (G1) GC

其中,Serial GC不應(yīng)該被用在服務(wù)器上。這種GC類型在單核CPU的桌面電腦時(shí)代就存在了。使用Serial GC會(huì)顯著的降低應(yīng)用的性能指標(biāo)。
現(xiàn)在,讓我們共同學(xué)習(xí)每一種GC類型

1. Serial GC (-XX:+UseSerialGC)

新生代空間的GC方式我們?cè)谇懊嬉呀?jīng)介紹過了,在老年代空間中的GC采取稱之為”mark-sweep-compact“的算法。

  1. 算法的第一步是標(biāo)記老年代中依然存活對(duì)象。(標(biāo)記)

  2. 第二步,從頭開始檢查堆內(nèi)存空間,并且只留下依然幸存的對(duì)象。(清理)

最后一步,從頭開始,順序地填滿堆內(nèi)存空間,并且將對(duì)內(nèi)存空間分成兩部分:一個(gè)保存著對(duì)象,另一個(gè)空著(壓縮)。

2. Parallel GC (-XX:+UseParallelGC)

圖 4: Serial GC 與 Parallel GC的區(qū)別

從上圖中,你可以輕易地看出serial GC和parallel GC的區(qū)別,serial GC只使用一個(gè)線程執(zhí)行GC,而parallel GC使用多個(gè)線程,因此parallel GC更高效。這種GC在內(nèi)存充足以及多核的情況下會(huì)很有用,因此我們也稱之為”throughput GC“。

3. Parallel Old GC(-XX:+UseParallelOldGC)

Parallel Old GC在JDK5之后出現(xiàn)。與parallel GC相比,唯一的區(qū)別在于針對(duì)老年代的GC算法。Parallel Old GC分為三步:標(biāo)記-匯總-壓縮(mark – summary – compaction)。匯總(summary)步驟與清理(sweep)的不同之處在于,其將依然幸存的對(duì)象分發(fā)到GC預(yù)先處理好的不同區(qū)域,算法相對(duì)清理來說略微復(fù)雜一點(diǎn)。

4. CMS GC (-XX:+UseConcMarkSweepGC)

圖 5: Serial GC & CMS GC

就像你從上圖看到的那樣, CMS GC比我之前解釋的各種算法都要復(fù)雜很多。第一步初始化標(biāo)記(initial mark) 比較簡(jiǎn)單。這一步驟只是查找那些距離類加載器最近的幸存對(duì)象。因此,停頓的時(shí)間非常短暫。在之后的并行標(biāo)記( concurrent mark )步驟,所有被幸存對(duì)象引用的對(duì)象會(huì)被確認(rèn)是否已經(jīng)被追蹤和校驗(yàn)。這一步的不同之處在于,在標(biāo)記的過程中,其他的線程依然在執(zhí)行。在重新標(biāo)記(remark)步驟,會(huì)再次檢查那些在并行標(biāo)記步驟中增加或者刪除的與幸存對(duì)象引用的對(duì)象。最后,在并行交換( concurrent sweep )步驟,轉(zhuǎn)交垃圾回收過程處理。垃圾回收工作會(huì)在其他線程的執(zhí)行過程中展開。一旦采取了這種GC類型,由GC導(dǎo)致的暫停時(shí)間會(huì)極其短暫。CMS GC也被稱為低延遲GC。它經(jīng)常被用在那些對(duì)于響應(yīng)時(shí)間要求十分苛刻的應(yīng)用之上。

當(dāng)然,這種GC類型在擁有stop-the-world時(shí)間很短的優(yōu)點(diǎn)的同時(shí),也有如下缺點(diǎn):

  •  它會(huì)比其他GC類型占用更多的內(nèi)存和CPU

  •  默認(rèn)情況下不支持壓縮步驟

在使用這個(gè)GC類型之前你需要慎重考慮。如果因?yàn)閮?nèi)存碎片過多而導(dǎo)致壓縮任務(wù)不得不執(zhí)行,那么stop-the-world的時(shí)間要比其他任何GC類型都長(zhǎng),你需要考慮壓縮任務(wù)的發(fā)生頻率以及執(zhí)行時(shí)間。

5. G1 GC

最后,我們來學(xué)習(xí)垃圾回收優(yōu)先(G1)GC類型。

圖 6:  G1 GC的結(jié)構(gòu)

 如果你想要理解G1,首先你要忘記你所學(xué)過的新生代和老年代的概念。正如你在上圖所看到的,每個(gè)對(duì)象被分配到不同的格子,隨后GC執(zhí)行。當(dāng)一個(gè)區(qū)域裝滿之后,對(duì)象被分配到另一個(gè)區(qū)域,并執(zhí)行GC。這中間不再有從新生代移動(dòng)到老年代的三個(gè)步驟。這個(gè)類型是為了替代CMS GC而被創(chuàng)建的,因?yàn)镃MS GC在長(zhǎng)時(shí)間持續(xù)運(yùn)作時(shí)會(huì)產(chǎn)生很多問題。

G1最大的好處是性能,他比我們?cè)谏厦嬗懻撨^的任何一種GC都要快。但是在JDK 6中,他還只是一個(gè)早期試用版本。在JDK7之后才由官方正式發(fā)布。就我個(gè)人看來,NHN在將JDK 7正式投入商用之前需要很長(zhǎng)的一段測(cè)試期(至少一年)。因此你可能需要再等一段時(shí)間。并且,我也聽過幾次使用了JDK 6中的G1而導(dǎo)致Java虛擬機(jī)宕機(jī)的事件。請(qǐng)耐心的等到它更穩(wěn)定吧。

下一次我將討論GC優(yōu)化相關(guān)的問題,但是在此之前我要先明確一件事情,假如應(yīng)用中創(chuàng)建的所有對(duì)象的大小和類型都是統(tǒng)一的,那么公司使用的WAS的GC參數(shù)可以是相同的。但是WAS所創(chuàng)建對(duì)象的大小和生命周期根據(jù)服務(wù)以及硬件的不同而不同。換句話說,不能因?yàn)槟硞€(gè)應(yīng)用使用的GC參數(shù)“A”,就說明同樣的參數(shù)也能給其他服務(wù)帶來最佳的效果。而是要因地制宜,有的放矢。我們需要找到適合每個(gè)WAS線程的參數(shù),并且持續(xù)的監(jiān)控和優(yōu)化每個(gè)設(shè)備上的WAS實(shí)例。這并不是我的一家之談,而是負(fù)責(zé)Oracle Java虛擬機(jī)研發(fā)的工程師在 JavaOne 2010上已經(jīng)討論過的。

本文中我們簡(jiǎn)略的介紹了Java的GC機(jī)制,請(qǐng)繼續(xù)關(guān)于我們的后續(xù)文章,我們將會(huì)討論如何監(jiān)控Java GC狀態(tài)以及優(yōu)化GC。

另外,我特別推薦一本2011年12月發(fā)布的《Java性能》(Amazon,也可以通過safari在線閱讀),還有在Oracle官網(wǎng)發(fā)布的白皮書《Java HotSpotTM虛擬機(jī)內(nèi)存管理》(這本書與Java性能優(yōu)化不是同一本) 作者Sangmin Lee, NHN公司,性能工程師實(shí)驗(yàn)室高級(jí)工程師。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Java虛擬機(jī)的JVM垃圾回收機(jī)制
垃圾回收
[譯]GC專家系列1:理解Java垃圾回收
聊聊JVM(二)說說GC的一些常見概念
Java之美[從菜鳥到高手演變]之JVM內(nèi)存管理及垃圾回收
Hotspot JVM的常用選項(xiàng)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服