JVM學習篇之-GC

原文轉自: https://blog.csdn.net/Strong997/article/details/80033787java

一、GC 算法

    垃圾收集 Garbage Collection 一般被稱爲「GC」,它誕生於1960年 MIT 的 Lisp 語言,通過半個多世紀,目前已經十分紅熟了。多線程

    jvm 中,程序計數器、虛擬機棧、本地方法棧都是隨線程而生隨線程而滅,棧幀隨着方法的進入和退出作入棧和出棧操做,實現了自動的內存清理,所以,咱們的內存垃圾回收主要集中於 java 堆和方法區中,在程序運行期間,這部份內存的分配和使用都是動態的.併發

二、對象存活判斷 jvm

    判斷對象是否存活通常有兩種方式:性能

        一、引用計數:每一個對象有一個引用計數屬性,新增一個引用時計數加1,引用釋放時計數減1,計數爲0時能夠回收。此方法簡單,沒法解決對象相互循環引用的問題。優化

        二、可達性分析(Reachability Analysis):從GC Roots開始向下搜索,搜索所走過的路徑稱爲引用鏈。當一個對象到GC Roots沒有任何引用鏈相連時,則證實此對象是不可用的。不可達對象。.net

        在Java語言中,GC Roots包括:線程

            一、虛擬機棧中引用的對象。指針

            二、方法區中類靜態屬性實體引用的對象。

            三、方法區中常量引用的對象。

           四、 本地方法棧中JNI引用的對象。

三、垃圾收集算法  

    3.1標記 -清除算法

        「標記-清除」(Mark-Sweep)算法,如它的名字同樣,算法分爲「標記」和「清除」兩個階段:首先標記出全部須要回收的對象,在標記完成後統一回收掉全部被標記的對象。

        它的主要缺點有兩個:一個是效率問題,標記和清除過程的效率都不高;另一個是空間問題,標記清除以後會產生大量不連續的內存碎片,空間碎片太多可能會致使,當程序在之後的運行過程當中須要分配較大對象時沒法找到足夠的連續內存而不得不提早觸發另外一次垃圾收集動做。

    3.2複製算法

        「複製」(Copying)的收集算法,它將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。

        這樣使得每次都是對其中的一塊進行內存回收,內存分配時也就不用考慮內存碎片等複雜狀況,只要移動堆頂指針,按順序分配內存便可,實現簡單,運行高效。只是這種算法的代價是將內存縮小爲原來的一半,持續複製長生存期的對象則致使效率下降。

    3.3標記-壓縮算法

        「標記-整理」(Mark-Compact)算法,標記過程仍然與「標記-清除」算法同樣,但後續步驟不是直接對可回收對象進行清理,而是讓全部存活的對象都向一端移動,而後直接清理掉端邊界之外的內存

    3.4分代收集算法

        「分代收集」(Generational Collection)算法,把Java堆分爲新生代和老年代,這樣就能夠根據各個年代的特色採用最適當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,只有少許存活,那就選用複製算法,只須要付出少許存活對象的複製成本就能夠完成收集。而老年代中由於對象存活率高、沒有額外空間對它進行分配擔保,就必須使用「標記-清理」或「標記-整理」算法來進行回收。
四、垃圾收集器

    4.1串行垃圾回收器Serial        

        串行回收器是指使用單線程進行垃圾回收的回收器,每次回收時串行回收器只有一個工做線程,對於併發能力較弱的計算機來講,串行回收器的專一性和獨佔性每每有更好的表現。串行回收器能夠在新生代和老年代使用,根據做用的堆空間不一樣,分爲新生代串行回收器和老年代串行回收器。

        Serial收集器是最古老的收集器,它的缺點是當Serial收集器想進行垃圾回收的時候,必須暫停用戶的全部進程,即stopthe world(服務暫停)。到如今爲止,它依然是虛擬機運行在client模式下的默認新生代收集器。

        參數控制:-XX:+UseSerialGC 使用串行收集器    


    4.2並行垃圾回收器 

        4.2.1並行垃圾回收器

                並行回收器是在串行回收器的基礎上作了改進,它可使用多個線程同時進行垃圾回收,對於計算能力強的計算機來講,能夠有效的縮短垃圾回收所需的實際時間        
        4.2.2並行垃圾回收器——ParNew

                ParNew收集器是一個工做在新生代的垃圾收集器,它只是簡單的將串行收集器多線程化,它的回收策略和算法和串行回收器同樣。新生代並行,老年代串行;新生代複製算法、老年代標記-壓縮。

                參數控制:-XX:+UseParNewGC 使用ParNew收集器     -XX:ParallelGCThreads 限制線程數量

        4.2.3並行垃圾回收器——Parallel

                Parallel是採用複製算法的多線程新生代垃圾回收器,Parallel收集器更關注系統的吞吐量。所謂吞吐量就是CPU用於運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量=運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)。

                停頓時間越短就越適合須要與用戶交互的程序,良好的響應速度可以提高用戶的體驗;

                而高吞吐量則能夠最高效率地利用CPU時間,儘快地完成程序的運算任務,主要適合在後臺運算而不須要太多交互的任務。

                能夠經過參數來打開自適應調節策略,虛擬機會根據當前系統的運行狀況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或最大的吞吐量;也能夠經過參數控制GC的時間不大於多少毫秒或者比例;新生代複製算法、老年代標記-壓縮

                參數控制:-XX:MaxGCPauseMillis 設置最大垃圾收集停頓時間    -XX:GCTimeRatio 設置吞吐量的大小(默認是99)    -XX:+UseAdaptiveSeizPolicy 打開自適應模式

        4.2.4並行垃圾回收器——Parallel Old

                Parallel Old收集器是Parallel Scavenge收集器的老年代版本,採用多線程和」標記-整理」算法,也是比較關注吞吐量。在注重吞吐量及CPU資源敏感的場合,均可以優先考慮Parallel Scavenge加Parallel Old收集器。

                參數控制:-XX:+UseParallelOldGC 使用ParallelOld收集器    -XX:ParallelGCThreads 限制線程數量

    4.3CMS垃圾回收器

        CMS(Concurrent Mark Sweep)併發標記請除,它使用的是標記請除法,工做在老年代,主要關注系統的停頓時間。

        CMS並非獨佔的回收器,也就是說,CMS回收的過程當中應用程序仍然在不停的工做,又會有新的垃圾不斷的產生,因此在使用CMS的過程當中應該確保應用程序的內存足夠可用,CMS不會等到應用程序飽和的時候纔去回收垃圾,而是在某一閥值(默認爲68)的時候開始回收,也就是說當老年代的空間使用率達到68%的時候回執行CMS。若是內存使用率增加很快,在CMS執行過程當中,已經出現了內存不足的狀況,此時,CMS回收就會失敗,虛擬機將啓動老年代串行回收器進行垃圾回收,這會致使應用程序中斷,直到垃圾回收完成後纔會正常工做,這個過程GC的停頓時間可能較長,因此閥值的設置要根據實際狀況設置。

        標記清除法的缺點是內存碎片問題,CMS提供提供了一些優化設置,能夠設置完成CMS以後進行一次碎片整理,也能夠設置進行多少次CMS回收後進行碎片整理

        參數控制:-XX:CMSInitatingPermOccupancyFraction 設置閥值    -XX:+UserConcMarkSweepGC 使用cms垃圾清理器    -XX:ConcGCThreads 限制線程數量    -XX:+UseCMSCompactAtFullCollection 設置完成CMS以後進行一次碎片整理    -XX:CMSFullGCsBeforeCompaction 設置進行多少次CMS回收後進行碎片整理

    4.4G1(Garbage First)垃圾回收器

        G1(Garbage First)垃圾收集器是當今垃圾回收技術最前沿的成果之一。早在JDK7就已加入JVM的收集器你們庭中,成爲HotSpot重點發展的垃圾回收技術。同優秀的CMS垃圾回收器同樣,G1也是關注最小時延的垃圾回收器,也一樣適合大尺寸堆內存的垃圾收集,官方也推薦使用G1來代替選擇CMS。G1最大的特色是引入分區的思路,弱化了分代的概念,合理利用垃圾收集各個週期的資源,解決了其餘收集器甚至CMS的衆多缺陷。

        並行與併發:G1能充分利用多CPU、多核環境下的硬件優點,使用多個CPU(CPU或者CPU核心)來縮短Stop-The-World停頓的時間,部分其餘收集器本來須要停頓Java線程執行的GC動做,G1收集器仍然能夠經過併發的方式讓Java程序繼續執行。

        分代收集:與其餘收集器同樣,分代概念在G1中依然得以保留。雖然G1能夠不需其餘收集器配合就能獨立管理整個GC堆,但它可以採用不一樣的方式去處理新建立的對象和已經存活了一段時間、熬過屢次GC的舊對象以獲取更好的收集效果。

        空間整合:與CMS的「標記-清理」算法不一樣,G1從總體看來是基於「標記-整理」算法實現的收集器,從局部(兩個Region之間)上看是基於「複製」算法實現,不管如何,這兩種算法都意味着G1運做期間不會產生內存空間碎片,收集後能提供規整的可用內存。這種特性有利於程序長時間運行,分配大對象時不會由於沒法找到連續內存空間而提早觸發下一次GC。

        可預測的停頓:這是G1相對於CMS的另一大優點,下降停頓時間是G1和CMS共同的關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲M毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已是實時Java(RTSJ)的垃圾收集器特徵了。

        參數控制:-XX:+UseG1GC 使用G1垃圾收集器    -XX:ParallelGCThreads 限制線程數量    -XX:MaxGCPauseMillis 指定最大停頓時間

相關文章
相關標籤/搜索