麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

JVM-垃圾收集器

2019-11-10 20:15:29
字體:
來源:轉載
供稿:網友

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

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

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

 

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

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

    垃圾收集器運行過程中必然會發生“Stop the world”,只是時間長短和暫停時間可不可控的區別。

    在進行下面的閱讀之前,首先明確在垃圾收集器中,“并發”和“并行”這兩個概念的差別:

并行(Parallel):多個垃圾收集線程并行工作,此時用戶線程處于等待狀態并發(Concurrent):垃圾收集線程和用戶線程同時執行(不一定是并行,可能是交替執行),用戶程序繼續執行,而GC運行在另一個CPU上

Serial

       Serial垃圾收集器,通過這個單詞的意思“連續”,我認為這個應該是指的GC之后內存空間不存在內存碎片的意思,那么必然不會采用“標記-清除算法”來實現,所以這個垃圾收集器在新生代使用的是“復制算法”,而Serial Old作為Serail收集器的老年代版本,使用的就是“標記-整理算法”。

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

ParNew-Parallel New

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

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

    ParNew在單CPU環境中收集效果不如Serial收集器,但是隨著CPU的增加,它對于GC時系統資源的利用還是很有好處的,默認開啟的線程數與CPU的數量一致 。

Parallel Scavenge

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

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

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

Serial Old

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

CMS

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

Parallel Old

    Parallel Old是Parallel Scavenge收集器的老年代版本,簡稱PS Old,使用了多線程和”標記-整理“算法,這個收集器是在JDK1.6中才提供的,在此之前PS new的地位比較尷尬,因為在此之前老年代的垃圾回收只有Serial Old這一種收集器,與Serial Old配合,Parallel Scavenge無法產生理想的回收效果,吞吐量在老年代很大且硬件比較高級的環境中可能還不如使用ParNew與CMS的組合”給力“,而PS Old產生之后,PS New才變得名副其實。    也就是說,在JDK1.6及之后,在注重吞吐量和CPU資源敏感的場合,都可以優先考慮PS New和PS Old的組合。

G1

       在JDK6u14中提供了Early access版本的G1收集器以供試用,直到JDK7u4的時候才正式發布。G1是一款面向服務端應用的垃圾收集器,HotSpot開發團隊賦予它的使命是未來替換掉CMS收集器,從這點上看,G1也是追求短停頓時間的。

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

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

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

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

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

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 在线免费亚洲 | 九九热精品在线视频 | 久久精品一二三区白丝高潮 | 欧美 亚洲 激情 | 久久99精品国产99久久6男男 | 亚洲成人高清在线观看 | 少妇的肉体的满足毛片 | 日本残忍极度灌浣肠视频 | 福利免费在线 | 蜜桃网站在线 | 操碰网 | 久久我不卡 | 国产一区网址 | 亚洲3atv精品一区二区三区 | 免费男女视频 | 一级免费黄色 | 在线日韩亚洲 | 毛片免费视频播放 | 欧美人与牲禽动交精品一区 | 一区二区三区黄色 | 性毛片视频 | 2017亚洲男人天堂 | 18被视频免费观看视频 | 久久久久久久久免费 | 成年人激情在线 | 国产一区二区三区视频在线 | 国产精品自拍片 | 精品一区二区三区中文字幕老牛 | 羞羞网站在线看 | 免费a视频在线观看 | 国产精品刺激对白麻豆99 | 国产午夜精品一区二区三区在线观看 | 亚洲精品a级 | 国产亚洲综合一区二区 | 欧美精品久久久久久久久久 | 亚洲影院在线播放 | 欧美成人影院 | 日韩在线欧美在线 | 成人午夜视频免费看 | 精品久久久久久成人av | 中文字幕精品一二三四五六七八 |