Java 垃圾回收一

 

1、判斷對象是否存活的算法:

<1>、引用計數法:(每個對象實例中都有一個引用計數器)當一個對象被創建的時候,該實例對象分配給一個變量,此時計數器爲1。之後當其他變量引用該對象實例時,計數器+1,而當引用的變量超過生命週期,或改變爲引用其他對象實例時,該對象實例計數器-1。當計數器爲0的時候,則說明該對象實例沒有被引用,即可以被垃圾回收掉。

缺點:當2個對象之間相互引用時,則這2個對象實例無法被回收掉,因爲他們之間相互引用。

         關於缺點的理解,僞代碼說明:

         {

                   O1 o1 = new O1();

                   O2 o2 = new O2();

                   o1.instance = o2;//實例O1中的一個成員變量是實例O2類型

                   o2.instance = o1;//實例O2中的一個成員變量是實例O1類型

                   o1 = null;//雖然o1 = null ,但是O2中的一個成員變量引用了O1的實例,即引用變量由 o1—>O2.instance

                   o2 = null;同理如上

         }

 

<2>、可達性分析:由定義好的GC Roots節點作爲起始點開始,將所有有聯繫的節點全部連接到一起,最終形成類似樹狀的結構,此時,不在樹上的節點即爲可回收對象

a、優點:解決了互相引用,無法回收的問題

b、GC Roots節點對象有如下幾種:

           1、方法區常量引用的對象

           2、方法區中靜態成員變量引用的對象

           3、虛擬機棧中引用的對象【棧楨中的本地變量表】

           4、本地方法棧中本地方法引用的對象

c、二次標記機制:在可達性分析中,當被確定爲可回收對象時,進行第一次標記。若該對象沒有重寫 finalize(),或者在重寫時,沒有爲自己與GC Roots 樹建立連接,此時進行第二次標記。二次標記結束後,當垃圾回收的時候,就會被回收掉。

注意:二次標記機制,finalize()中建立與GC Roots 樹連接,一個對象只有一次機會,不會通過在finalize()中建立與GC Roots 樹連接,出現一直無法回收的現象。

 

 

2、方法區垃圾回收

方法區中被回收的對象有2種:1、廢棄常量;2、無用的類

<1>、廢棄常量通過可達性分析 來判斷

<2>、無用的類通過以下幾點來判斷是否回收:

             1、該類所有的實例都被回收

             2、加載該類的ClassLoader 被回收

             3、該類對應的Java.lang.Class 對象沒有任何地方引用,同時無法通過反射來獲取該類的方法等等。

 

 

3、垃圾回收的算法

<1>、標記清除算法

採用從 GC Roots 點開始掃描,對存活的對象進行標記,標記結束之後,再掃描整個空間中未被標記的對象進行回收。

缺點:產生內存碎片

<2>、複製回收算法 ---  解決句柄的開銷和內存碎片的問題

將空間分爲2部分,同樣從GC Roots節點開始掃描,將存活的對象複製到另外一半中,全部掃描結束後,清空原來一半空間。

優點:不會產生內存碎片,高效

缺點:佔用內存空間大

<3>、標記整理算法

標記所有存活的對象,掃描並清除整個空間中未標記的對象,在回收死亡的對象時,將存活的對象往左邊空閒空間移動,建立在標記清除算法之上

優點:不會產生內存碎片

缺點:開銷大

<4>、分代收集算法

目前大部分JVM使用的垃圾回收算法,核心思想是根據對象生命週期劃分爲若干個不同區域:新生代、老年代。新生代由於每次回收時都有大量的對象需要被回收、老年代的特點是每次垃圾回收時,只有少量對象被回收。因此,可以根據不同的區域使用不同的垃圾回收算法。

年輕代回收算法-複製回收算法(分區比例是8:1:1);老年代中回收的對象少,適合標記整理 和標記清除算法

過程:

將年輕代分爲  Eden區、s0(From)區、s1(To)區。新對象產生一般在Eden區,如果Eden區滿了,則將Eden區中存活的對象複製到s0區-箭頭1,清空Eden區【young  GC】;如果s0區滿了,則將Eden區和s0區中存活的對象複製到s1區-箭頭2,清空Eden區 和 s0區【young GC】,同時將s0於s1 互換一下 -箭頭2.5,確保s1區是空的。同時如果其中的對象達到了閾值(在s區中經歷默認爲15次young GC之後),就將達到閾值的對象放入老年代中。

如果s1區不足以存放Eden區和s0區中存活的對象則 將存活的對象直接複製到老年代 - 箭頭3。如果老年代也滿了,則會觸發一次Full GC,頻率低

如果Eden區不足以存放新建的對象,則會觸發擔保機制,將新建對象直接存儲到老年代中。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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