天天看點

Java垃圾回收(GC)機制總結

概述

          本文彙總了垃圾回收(GC)相關知識,精煉了部分了解複雜的部分,可能會忽略某些特殊情況,是對GC的總體整理分析。

哪些區域需要回收?

          java記憶體可大體分為:方法區,堆(heap),虛拟機區,本地方法棧,程式計數器(PC),這五塊。虛拟機區,本地方法棧,程式計數器(PC)與具體線程綁定,生命周期和線程相同,某個線程回收時,與此線程綁定三塊區域記憶體同時回收。而方法區,堆(heap)是由所有線程共用。同時也是java程式記憶體使用的大部分,存放着類和對象。

          java的GC針對的是:方法區和堆區域的記憶體回收。

如何知道哪些對象需要回收?

          1.引用計數法:給對象添加一個引用計數器,當增加一個引用時+1,引用失效時-1.為0則清除。

                     注意:出現形似于下圖的引用關系(循環引用)時,當棕色的引用消失時,從邏輯上不再對小圓引用,但是所有的小圓的引用計數仍都為1,是以都不會清除。這種情形引用計數法就捉襟見肘。

Java垃圾回收(GC)機制總結

          2. 可達性法分析:首先認為Root開始搜尋,如果沒有搜尋到則認為不可達,則該對象邏輯上不再被使用,需要清除。Root的數目并不止一個,需要一個 GC Root Set 去保證 仍需要使用的對象不會被清除。

           可被選為GC Roots Set的對象有以下四種

                      1.棧幀中的本地變量表(局部變量表)中的引用對象。

                      2.方法區中的類靜态屬性引用的對象。

                      3.方法去中常量引用的對象。

                      4.本地方法棧中JNI引用的對象。

         3.四種引用分析:https://blog.csdn.net/qq_36144187/article/details/81564747

類的回收:

        需要同時滿足下列三個條件,才有可能被回收,僅僅是有可能。

                1.該類的所有執行個體都已經被回收。

                2.加載該類的ClassLoader被回收

                3.對應的java.lang.Class 對象沒有在任何地方被引用。

基礎垃圾收集算法

       1.标記--清除算法

               分為兩個階段,标記出需要回收的對象,然後回收。

               缺點:會産生大量的碎片,容易觸發更多次的GC。

       2.标記--整理算法

               分為兩個階段,标記存活的對象,然後把存活移動到一段,回收所有邊界之外的記憶體。

               缺點:單次的GC時間更長,

       3.複制算法

               将記憶體劃為大小完全一樣的兩塊記憶體,隻是用其中的一塊,每次gc就将所有存貨對象,移到另一塊,清除本塊記憶體。

               缺點:會浪費50%的記憶體

垃圾收集基本思想

        1.分代思想:把堆分為新生代,老年代,s0,s1這四塊。不同的區域使用不同的算法。一般對象配置設定在新生代,當新生代滿觸發 Minor GC。若對象可以s區域,則移入s區域,這個區域采用複制算法,多次仍存在,則移入老年代,老年代滿觸發 Major GC。或者大對象直接在老年代配置設定。Full GC 則是對整個堆進行GC操作。

        2.Stop-The-World:就是全局停頓,因為當記憶體在被使用時,總是會産生垃圾,若一邊清理一邊運作,那麼垃圾總是清理不幹淨,更重要的是标記--整理算法将無法使用。

綜合垃圾收集器

        1.串行收集器(SerialGC):

                   1.最古老,最穩定

                   2.可能會産生較長時間的停頓

                   3. -XX:+UseSerialGC

                            - 新生代,老年代使用串行回收

                            - 新生代複制算法

                            - 老年代标記-壓縮

          2.ParNew:

                   1.新生代并行,老年代串行。

                   2.可以了解為Serial在新生代的并行版本

                   3. -XX:+UseParNewGC

                            - 多線程支援多核

                            -  -XX:ParallelGCThreads 限制線程數量

                            - 基本和串行收集器一緻

           3.CMS收集器

                   1.停頓時間短,清理不能完全幹淨

                   2.采用标記-清除算法

                   3.不能在快滿的使用

                   4. -XX:+UseConcurrentMarkSweepGC

                            - 并發階段會降低吞吐量

                            -  針對老年代

                            - 新生代仍用ParNew

                   5.工作流程:

                            -初始标記:根可以直接關聯到的對象

                            -并發标記:一邊運作一邊标記全部對象

                            -重新标記:産生 Stop The world ,修正并發标記

                            -并發清除:基于标記結果直接清理對象

           4.G1收集器

                   1.取消新生代老年代的實體隔離,使用大小相同的Region分割堆。

                   2.停頓時間可以預測控制

                   3.整體上采用标記-整理,局部來看采用兩個Region之間的複制算法

                   4. -XX:+UseConcurrentMarkSweepGC

                            - 優化了大于4G以上的超大堆

                            -  充分利用Cpu和多核環境,适合現代的算法

                            - 增加了與 Region關聯的 Remembered Set 避免全堆掃描

                   5.工作流程:與CMS流程大緻相同。

總結                          

             記憶體回收和垃圾收集器雖然影響程式的并發性,吞吐率。但仍需一個良好的程式才能發揮調優的作用。同時沒有固定的收集器、參數的組合,隻能針對不同的程式調優。

             本文引用:

                    《深入了解JVM》   周志明

                      煉數成精   JVM相關課程

                      http://blog.jobbole.com/109170/       

繼續閱讀