第四章 HotSpot jvm 中的垃圾回收機制

有很多有名的Jvm,但我們最常用到的就是Oracle收購sun公司的HotSpot。

HotSpot中內存被分爲3個代:年輕代(young generation),年老代(old generation),持久代(permanent generation)。對象最初在年輕代,年老代代理存放着是經過幾次年輕代收集後仍然 live 的對象和一些可能直接被分配到年老代的大對象。持久代存放的是 JVM 認爲可以幫助簡化垃圾收集管理的對象,比如像類和方法的描述信息。


年輕代代內存模型:一個伊甸區(Eden),加上兩個小代生還區(survivor space)

wKiom1bphpKjQgYqAABr_eWR7GU051.png

大部分對象是直接分配在伊甸區(有一些大的對象可能直接分配在年老代),最後一次垃圾回收後還生存代對象保存在生還區,它們在晉升到年老代之前還是有可能會死掉。這種對象被保存在from區中。

一個收集器可能會有多個算法,一些用於年輕代,一些用於年老代。但除了CMS收集器,其它代收集器會在年輕代使用年老代的收集算法,每當年老代被佔用代太慢了。CMS收集器沒有這樣的原因是因爲CMS算法不能用於在年輕代上。


快速分配:在很多情況下都存在一個連續的很大的內存塊用於分配。這時候可以用一種被稱之爲空閒指針的簡單點技術在這塊內存上進行分配。這種技術就是用一個指針來保存每次分配的痕跡,當再次有分配的請求時,就檢查新對象是否可以放下,如果能就更新指針初始化對象。



下面介紹幾種收集器:


串行收集(Serial Collector):

        不管年輕代還是年老代都是串行代,就是隻使用一個cpu,這種收集器使用的是停止一切的模式。


串行收集器的年輕代工作步驟:

        在伊甸區存活的對象除了太大的不適合放入的對象都要複製到TO生還區,那些太大的對象直接放入了年老代。另一個from生還區中對象較爲年輕代也放入了TO生還區,年老的則複製到了年老代。如果TO區滿了的話,就無法在放入了,滿、那麼伊甸區和from區的存活的對象直接晉升到年老代。複製完成後不需要任何檢查,因爲留在伊甸區和From區的都不是存活的對象。(這裏沒有使檢查或標記的算法)

wKiom1bphs7AsQWyAACS2UcHKmc361.png

在年輕代收集完一次之後,伊甸區和From區裏都是空的了,只有To區海有對象,這時兩個生化區交換角色。


串行收集器的年老代工作步驟

        使用標記-清掃-壓縮的算法。標記是:標記收集器中海油哪些對象是和根節點向連的,是存活的。清掃是:掃蕩整個代識別垃圾。壓縮是:移動壓縮,將存活的對象移動到代的前端,在末尾留下一整塊的連續的空間空間,之後就可以泗洪 空閒指針來標記。


在什麼時候使用這種串行的收集器?

        一般都是在客戶端環境(非服務器級別動),對短暫停可以忍受的程序中。現在串行收集器可以有效的管理擁有64M堆內存的應用程序。

串行收集器可以使用  -XX:UseSerialGC 指令來指出我要使用串行收集器。



並行收集器(Parallel Collector):

        先如今基本上都是多核處理的機器,這樣隨之有利用多核優勢的收集器被設計出來,不至於讓許多cpu處於空閒狀態。


並行收集器的年輕代:

        和串行不同的是,這裏使用的是串行年輕代收集的一個並行的版本,也仍然是 stop the world的複製算法。但使用了多個cpu,因此是很快的,增加了吞吐量。

wKioL1bph4HAMRdgAABd0Wm4R5o143.png


並行收集器的年老代和串行的一樣。



並行壓縮收集器(Paralle Compacting Collector)

        它於並行收集不同地方就在在年老代上的收集使用了一種新的算法。


並行壓縮的年老代收集

使用的是並行的平行壓縮算法和stop the world模式。此算法可以分爲三個階段:

     

    標記階段,在最初的應用程序中代碼能夠直接到達的對象分給垃圾回收線程,然後開始並行的標記所有這些能夠直接到達(活着)的對象,如果一個對象是活着的,那麼這個對象的大小和所在的位置就會更新在它的區域數據中。


     摘要階段,作用在區域上,而不是對象上:通常經過幾個週期短壓縮後每個代代左側是很稠密的,存放着的對象大部分都是活着的,所以壓縮它們是很不值得的。所以在這個階段收集器所做的第一件事情就是要檢查區域的密度,加入密度達到某一個值時,從這個點及其右側到區域都要進行垃圾回收(壓縮)。在這個階段計算的是每個被壓縮區域中的存活對象的第一個字節的位置。


     壓縮階段,垃圾收集線程是要利用再要數據確定哪些適區域是要填滿的,然後每個線程對立的拷貝數據到對應的區域中。最後產生一個在一端很稠密在一段很大的空閒空間


     ps:我的理解,標記階段和摘要階段實在爲壓縮階段做準備,標記階段是先找到一個大概的位置,摘要階段是確定哪些是需要進行壓縮的,最後在到壓縮階段進行壓縮。


何時使用並行壓縮:

     並行壓縮收集器就是在並行收集器上在年老代的時候多使用了個並行的壓縮算法,這使得它在多個cpu的機器上擁有更好的性能,比如能夠減少暫停時間。這種收集器不適合仔大型共享機器上運行程序,因爲這些機器上一個程序不能獨佔多個cpu太長時間,在這些機器上應當考慮減少垃圾收集線程(使用命令行參數 -XX:ParallelGCThreads=n)或者選擇不同的收集器。如果想使用這個收集器,可以通過使用命令行參數:

—XX:UseParalleOldGC





今天寫的太晚了,CMS收集器(併發標記-清掃收集器)明天再寫吧(這個是可以使響應速度變的很快的收集器) 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章