国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

JVM-垃圾收集器

2019-11-10 20:42:32
字體:
供稿:網(wǎng)友

原文地址http://blog.csdn.net/zhshulin/article/details/50614477

通過學(xué)習(xí)了解到現(xiàn)在商用的JVM中的垃圾收集采用的是分代收集算法,即針對不同年代采用不同的收集算法。在JVM中,GC主要作用于堆內(nèi)存中,堆內(nèi)存又被劃分為新生代和老年代,由于新生代對象絕大多數(shù)是朝生夕死,而老年代相對存活時(shí)間就很長,故而需要使用不同的垃圾收集機(jī)制,所以垃圾收集器也就分為新生代收集器和老年代收集器,兩者相互組合進(jìn)行JVM堆內(nèi)存的空間回收(下圖中相連的垃圾收集器表示可以相互組合,注意Serial Old和CMS也可以聯(lián)合進(jìn)行老年代的垃圾收集)。JDK6u14中開始測試的G1垃圾收集器,正式發(fā)布于JDK7u4中,是目前唯一不需要依賴其他垃圾收集器即可完成新生代和老年代內(nèi)存收集。閱讀之前先了解,GC的兩個(gè)指標(biāo):暫停時(shí)間-應(yīng)對與存在大量用戶交互的場景;吞吐量-應(yīng)對后臺計(jì)算任務(wù)。

新生代的垃圾收集器有:Serial收集器、ParNew收集器、Parallel Scavenge收集器老年代的垃圾收集器有:Serial Old收集器、Parallel Old收集器、CMS收集器G1收集器。http://f.dataguru.cn/thread-514678-1-1.html

 

筆者使用的是JDK7u51,也就是JDK1.7.0_51

    下面我將試著通過自己的理解來分析各個(gè)垃圾收集器的特點(diǎn),目前并沒有一個(gè)適用于任何場景的垃圾收集器,所以選擇何種垃圾收集器進(jìn)行配合是根據(jù)具體應(yīng)用來區(qū)別對待的,那么了解各種垃圾收集器的特點(diǎn)以及他們之間是否可以相互配合,就十分重要了。

    垃圾收集器運(yùn)行過程中必然會(huì)發(fā)生“Stop the world”,只是時(shí)間長短和暫停時(shí)間可不可控的區(qū)別。

    在進(jìn)行下面的閱讀之前,首先明確在垃圾收集器中,“并發(fā)”和“并行”這兩個(gè)概念的差別:

并行(Parallel):多個(gè)垃圾收集線程并行工作,此時(shí)用戶線程處于等待狀態(tài)并發(fā)(Concurrent):垃圾收集線程和用戶線程同時(shí)執(zhí)行(不一定是并行,可能是交替執(zhí)行),用戶程序繼續(xù)執(zhí)行,而GC運(yùn)行在另一個(gè)CPU上

Serial

       Serial垃圾收集器,通過這個(gè)單詞的意思“連續(xù)”,我認(rèn)為這個(gè)應(yīng)該是指的GC之后內(nèi)存空間不存在內(nèi)存碎片的意思,那么必然不會(huì)采用“標(biāo)記-清除算法”來實(shí)現(xiàn),所以這個(gè)垃圾收集器在新生代使用的是“復(fù)制算法”,而Serial Old作為Serail收集器的老年代版本,使用的就是“標(biāo)記-整理算法”。

    為什么先說Serial垃圾收集器,是因?yàn)檫@個(gè)收集器是最基本、歷史最悠久的收集器,在JDK1.3.1之前,是JVM新生代收集的唯一選擇。Serial收集器是一個(gè)單線程的收集器,這個(gè)“單線程”是指JVM在使用它進(jìn)行GC的時(shí)候,必須暫停其他所有的工作線程(sun將這件事情稱為“Stop the world”),直到GC完成,這是一件非常可怕的事情。看到這里,你可能想我一定要修改我的JVM的新生代收集器,不用Serial了,但是直至現(xiàn)在,Serial依然是JVM在運(yùn)行Client模式下默認(rèn)的新生代 收集器。與其他垃圾收集器的單線程相比,Serial簡單而高效。對于用戶桌面應(yīng)用場景來說,分配給JVM的內(nèi)存一般不會(huì)太大,收集十幾甚至一兩百兆的內(nèi)存,停頓時(shí)間可以控制在幾十毫秒,最多一百多毫秒以內(nèi),只要不是特別頻繁,這些停頓還是可以接受的。所以,對于Client模式下的JVM來說,Serial是個(gè)很好的新生代收集器,簡單高效。

ParNew-Parallel New

       ParNew收集器也是一個(gè)新生代收集器,其實(shí)就是Serial收集器的多線程版本,是一個(gè)“并行”的垃圾收集器,除了多線程外,其他和Serial差不多。想想也就明白了,當(dāng)JVM團(tuán)隊(duì)開發(fā)出來了Serial,可以滿足Client模式下的JVM,但是對于Server模式下的JVM來說,運(yùn)行很長時(shí)間,有很多的對象需要收集(可能幾十個(gè)G),單線程導(dǎo)致的停頓時(shí)間太長了(比如每運(yùn)行1小時(shí)需要停頓5分鐘),用戶無法接受業(yè)務(wù)線程停頓那么長的時(shí)間,我猜測這種情況下那些大牛能想到的最簡單的辦法就是讓Serial變成多線程,這樣開多個(gè)線程就可以有效的降低停頓時(shí)間,故而這個(gè)Serial的多線程版本也就誕生了。

    ParNew是許多運(yùn)行在Server模式下的JVM中首選的垃圾收集器,其中一個(gè)重要原因就是除了Serial,它是唯一可以和CMS(Concurrent Mark Sweep)老年代垃圾收集器配合工作。

    ParNew在單CPU環(huán)境中收集效果不如Serial收集器,但是隨著CPU的增加,它對于GC時(shí)系統(tǒng)資源的利用還是很有好處的,默認(rèn)開啟的線程數(shù)與CPU的數(shù)量一致 。

Parallel Scavenge

    Parallel Scavenge收集器,簡稱PS收集器,它和ParNew收集器一樣是一個(gè)多線程的并行新生代垃圾收集器,一樣采用“復(fù)制算法”(始發(fā)于JDK1.4.0)。那為什么還要這個(gè)PS收集器呢?現(xiàn)在想一下,ParNew收集器為什么會(huì)產(chǎn)生,不就是閑Serial收集器導(dǎo)致的“Stop the world”的時(shí)間太長了嘛,搞個(gè)多線程,減少停頓時(shí)間。這種的垃圾收集器適合重視服務(wù)的響應(yīng)速度的應(yīng)用程序(比如購物網(wǎng)站,肯定希望停頓時(shí)間越短越好,這樣用戶體驗(yàn)才好),但是對于一個(gè)后臺計(jì)算任務(wù)(比如MaPReduce)來說,沒有太多的交互任務(wù),那么它所重視的就不是這種響應(yīng)速度,而是CPU的有效時(shí)間利用率(這是我的理解),官方稱之為“吞吐量(Throughtput)”。吞吐量就是指CPU用來運(yùn)行用戶代碼的時(shí)間和CPU的總消耗時(shí)間的比值,即吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+GC消耗的時(shí)間)。

    Parallel Scavenge收集器正是基于對“吞吐量”的追求而產(chǎn)生的,它的目標(biāo)就是達(dá)到一個(gè)可控的吞吐量。由于與吞吐量關(guān)系密切,Parallel Scavenge收集器也被稱為“吞吐量優(yōu)先“收集器。Parallel Scavenge提供了兩個(gè)參數(shù)用來精確控制吞吐量,分別是控制最大垃圾收集停頓時(shí)間的-XX:MaxGCPauseMillis參數(shù)(單位:毫秒),以及直接設(shè)置吞吐量大小的-XX:GCTimeRatio參數(shù)(0-100之間,不包括首尾)。GCTimeRatio參數(shù)的計(jì)算規(guī)則是,比如設(shè)成19,那么允許最大時(shí)間就占總時(shí)間的5%,即1/(1+19),默認(rèn)值是99,也就是默認(rèn)允許最大GC時(shí)間占比是1%。

    Parallel Scavenge收集器還有一個(gè)參數(shù)來開啟GC的自適應(yīng)調(diào)節(jié)策略,只需要將JVM基本內(nèi)存設(shè)置好,并且制定上述兩個(gè)參數(shù)中的一個(gè)來作為JVM的優(yōu)化目標(biāo),那么JVM就可以根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動(dòng)態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時(shí)間或者最大吞吐量,這個(gè)參數(shù)就是-XX:+UseAdaptiveSizePolicy。自適應(yīng)調(diào)節(jié)策略也是PS收集器 相對于ParNew收集器的一個(gè)重要區(qū)別。ParNew收集器需要手工指定新生代大小(-Xmn)、Eden與Survivor的比例(-XX:SurvivorRatio)、晉升老年代對象年齡(-XX:PretenureSizeThreshold)等細(xì)節(jié)參數(shù)。

Serial Old

       Serial收集器的老年代版本,自然也是JVM中最早的老年代垃圾收集器,又稱為PS MarkSweep。它與Serial收集器一樣是一個(gè)單線程收集器,使用”標(biāo)記-整理算法“。這個(gè)收集器的主要一樣也是被Client模式下的JVM使用。如果在Server模式下,它主要有個(gè)兩大用途:在JDK1.5和之前的版本中與Parallel Scavenge收集器搭配使用,因?yàn)榇藭r(shí)CMS還沒有,CMS正式發(fā)布于JDK1.6中在JDK1.6和以后的版本中,作為CMS收集器的后備預(yù)案,在并發(fā)收集發(fā)生Concurrent Mode Failure的時(shí)候使用。    現(xiàn)在JDK已經(jīng)發(fā)展到了JDK8了,大量系統(tǒng)使用的穩(wěn)定版本也是JDK1.6和JDK1.7,所以第一種用途幾乎沒什么意義了,第二種還在用。PS:為何在JDK1.4的時(shí)候,新生代已經(jīng)有了Serial、ParNew和Parallel Scavenge這三種收集器,而老年代此時(shí)還是只有Serial Old這一種最原始的單線程收集器,個(gè)人推測,是由于Young GC發(fā)生的頻率遠(yuǎn)遠(yuǎn)高于Full GC,故而如何有效提高Young GC的收集效率減少停頓時(shí)間和增加吞吐量才是JDK1.4及之前的時(shí)間里JVM研發(fā)團(tuán)隊(duì)的首要任務(wù),當(dāng)對新生代的垃圾收集做到不錯(cuò)的程度的時(shí)候(有了并行收集器),工作重心才轉(zhuǎn)移到老年代的垃圾收集上,這就是一個(gè)工作的優(yōu)先級問題,畢竟每個(gè)人、每個(gè)團(tuán)隊(duì)、每個(gè)公司都避免不了的只有有限的精力和資源。在JDK1.5的時(shí)候推出了新的老年代收集器CMS,JDK1.6的時(shí)候推出了Parallel Old。

CMS

        在面對新生代的時(shí)候,垃圾收集器有兩種提升的方式,一種是減少用戶線程暫停的時(shí)間,另一種是提高”吞吐量“。假設(shè)現(xiàn)在處于JDK1.4發(fā)布到1.5發(fā)布之間,你要設(shè)計(jì)一個(gè)老年代的垃圾收集器,當(dāng)前只有Serial Old一種,那么如果讓你來選,你優(yōu)先提高GC的何種性能呢?前面也分析了”Stop the world“和”吞吐量“性能提升所應(yīng)對的場景,那么再問你,你覺得優(yōu)先提高JVM老年代垃圾收集來滿足用戶對響應(yīng)速度的需求比較重要,還是優(yōu)先提高JVM老年代垃圾收集來滿足后臺的計(jì)算任務(wù)呢?JDK1.4于2002年2月發(fā)布,那是java已經(jīng)比較火了,從96年開始JAVA就被用來制作網(wǎng)頁了,那么顯然用戶對于響應(yīng)速度的提升需求比較強(qiáng)烈,那么對于JVM項(xiàng)目組來說在已經(jīng)有了3種新生代垃圾收集器的前提下,研發(fā)一款減少用戶線程停頓時(shí)間的老年代垃圾收集器是必然的,所以在2004年9月,歷時(shí)兩年半,發(fā)布了JDK1.5,有了CMS垃圾收集器(Concurrent Mark Sweep)。(以上均為個(gè)人推測,與事實(shí)不符概不負(fù)責(zé))    CMS,Concurrent Mark Sweep,從名字就可以看出來這是一個(gè)基于”標(biāo)記-清除“算法的并發(fā)垃圾收集器(注意并發(fā)和并行的區(qū)別),用于老年代的垃圾收集,它在Sun的一些文檔中被稱為并發(fā)低停頓收集器(Concurrent Low Pause Collector)。CMS收集器是一種以獲取最短停頓時(shí)間為目標(biāo)的收集器,優(yōu)先滿足重視服務(wù)響應(yīng)速度的需求。CMS的運(yùn)行過程相對前面幾種收集器來說比較復(fù)雜,整個(gè)過程分為4步:初始標(biāo)記:僅僅標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快并發(fā)標(biāo)記:GC Roots Tracing,梳理引用鏈重新標(biāo)記:修正并發(fā)標(biāo)記過程中,用戶線程運(yùn)行導(dǎo)致標(biāo)記變動(dòng)的那一部分對象的標(biāo)記記錄。并發(fā)清除    其中,初始標(biāo)記和重新標(biāo)記都需要”Stop the world“,但是整個(gè)過程中耗時(shí)最長的并發(fā)標(biāo)記和并發(fā)清除階段都是可以與用戶線程一起工作的,所以總體來說,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)地執(zhí)行的。    雖然CMS很優(yōu)秀,是HotSpot虛擬機(jī)中有史以來的第一款真正意義上的并發(fā)收集器,但是CMS還遠(yuǎn)遠(yuǎn)達(dá)不到完美的程度,它有三個(gè)顯著的缺點(diǎn):對CPU資源非常敏感無法處理浮動(dòng)垃圾,所謂的浮動(dòng)垃圾就是CMS并發(fā)清除階段用戶線程運(yùn)行產(chǎn)生的垃圾,這部分垃圾必須等待下一次的垃圾收集來清除。所以CMS執(zhí)行GC的時(shí)候需要預(yù)留足夠的內(nèi)存空間(默認(rèn)32%,可調(diào)節(jié))給用戶線程使用,如果預(yù)留空間無法滿足用戶線程的內(nèi)存需求,那么就會(huì)發(fā)生“Concurrent Mode Failure”失敗,然后虛擬機(jī)就會(huì)啟動(dòng)Serial Old來重新進(jìn)行老年代的垃圾收集,這樣就會(huì)導(dǎo)致停頓時(shí)間很長了。會(huì)產(chǎn)生空間碎片(”標(biāo)記清除“算法的特點(diǎn)),CMS在Full GC發(fā)生之后附帶了一次碎片整理過程,而內(nèi)存整理是無法并發(fā)的,導(dǎo)致停頓時(shí)間不得不變長。發(fā)生這個(gè)問題的時(shí)候,可能就會(huì)調(diào)用Serial Old來處理老年代的垃圾回收了。

Parallel Old

    Parallel Old是Parallel Scavenge收集器的老年代版本,簡稱PS Old,使用了多線程和”標(biāo)記-整理“算法,這個(gè)收集器是在JDK1.6中才提供的,在此之前PS new的地位比較尷尬,因?yàn)樵诖酥袄夏甏睦厥罩挥蠸erial Old這一種收集器,與Serial Old配合,Parallel Scavenge無法產(chǎn)生理想的回收效果,吞吐量在老年代很大且硬件比較高級的環(huán)境中可能還不如使用ParNew與CMS的組合”給力“,而PS Old產(chǎn)生之后,PS New才變得名副其實(shí)。    也就是說,在JDK1.6及之后,在注重吞吐量和CPU資源敏感的場合,都可以優(yōu)先考慮PS New和PS Old的組合。

G1

       在JDK6u14中提供了Early access版本的G1收集器以供試用,直到JDK7u4的時(shí)候才正式發(fā)布。G1是一款面向服務(wù)端應(yīng)用的垃圾收集器,HotSpot開發(fā)團(tuán)隊(duì)賦予它的使命是未來替換掉CMS收集器,從這點(diǎn)上看,G1也是追求短停頓時(shí)間的。

    G1收集器與上述的6種收集器相比,具有以下的特點(diǎn):

并行和并發(fā):G1收集器不僅能充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢來減少停頓時(shí)間,而且仍可以通過并發(fā)的方式讓用戶線程繼續(xù)執(zhí)行分代收集:雖然在使用G1收集器的時(shí)候,JAVA堆的內(nèi)存布局已經(jīng)不再是物理隔離了,僅僅是邏輯隔離,但是分代的概念得到保留,G1可以獨(dú)立管理整個(gè)GC堆空間整合:CMS采用了“標(biāo)記-清除”算法,會(huì)產(chǎn)生內(nèi)存碎片。而G1整體看來采用的是“標(biāo)記-整理”算法,局部看來采用的是“復(fù)制”算法,故而G1運(yùn)行期間都不會(huì)產(chǎn)生內(nèi)存碎片,這種特性有利于程序長時(shí)間的運(yùn)行。可預(yù)測停頓:這是G1相比較CMS的一大優(yōu)勢,G1除了和CMS一樣追求低停頓外,還能建立可預(yù)測的停頓模型,能讓使用者明確指定在一個(gè)長度為M毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不超過N毫秒,這幾乎已經(jīng)是實(shí)時(shí)JAVA(RTSJ)垃圾收集器的特征了。

    G1最大的特點(diǎn)在我看來就是G1將Java堆劃分成多個(gè)大小相等的獨(dú)立區(qū)域(Region),雖然保留了新生代和老年代的概念,但是它們已經(jīng)不再是物理隔離了,而都是一部分Region的集合。G1在后臺維護(hù)一個(gè) 優(yōu)先列表,這個(gè)列表中保存了G1收集到的各個(gè)Region里面的垃圾堆積的價(jià)值大小(回收所獲得的空間大小以及回收需要的時(shí)間的經(jīng)驗(yàn)值),當(dāng)需要進(jìn)行垃圾回收的時(shí)候,根據(jù)用戶允許的收集時(shí)間,優(yōu)先回收列表中價(jià)值最大的那個(gè)Region(這就是Garbage-First,G1名字的由來)。這種使用Region劃分空間以及根據(jù)優(yōu)先級的區(qū)域回收方式,保證了G1收集器可以在有效的時(shí)間內(nèi)獲得盡可能高的收集效率,同時(shí)也避免了在整個(gè)JAVA堆中進(jìn)行全區(qū)域的垃圾收集。

    G1產(chǎn)生的原因我認(rèn)為就是HotSpot團(tuán)隊(duì)對于低延時(shí)和吞吐量兩者同時(shí)考慮,不斷追求一個(gè)完美的垃圾收集器的產(chǎn)物,雖然在執(zhí)行流程上和CMS有差不多,并且在初始標(biāo)記和最終標(biāo)記階段都需要暫停用戶線程,但是通過重新定義JAVA堆,引出了Region的概念,成功的讓其在性能上能兼顧到低延時(shí)和吞吐量,且不需要依賴其他收集器。G1的未來就是優(yōu)化初始標(biāo)記和最終標(biāo)記階段,如果能解決這兩個(gè)階段的用戶線程暫停,實(shí)現(xiàn)并發(fā),那么就很有可能產(chǎn)生一個(gè)近似理想狀態(tài)的一個(gè)垃圾收集器。

    不過用戶對于新生事物必須的認(rèn)同需要一定的時(shí)間,并且之前垃圾收集器相互配合也可以滿足用戶需求,那么G1對于大多數(shù)公司來說不是必需品,但是,隨著技術(shù)的不斷成熟,我認(rèn)為G1很有可能成為Server模式下的HotSpot默認(rèn)的收集器。

    對于G1收集器,可以參考:http://f.dataguru.cn/thread-514678-1-1.html


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 高尔夫| 西和县| 大洼县| 郑州市| 淮阳县| 白城市| 札达县| 临西县| 南部县| 博罗县| 江川县| 平江县| 宁国市| 天等县| 贵阳市| 江源县| 石林| 田阳县| 资中县| 张北县| 呼和浩特市| 枝江市| 新河县| 宽城| 曲靖市| 上犹县| 东城区| 东乌珠穆沁旗| 平度市| 香河县| 巴南区| 安庆市| 白水县| 尚志市| 化德县| 南丹县| 渝北区| 昌宁县| 佛山市| 阿合奇县| 宝山区|