深入理解java虛擬機器---垃圾收集器和分配策略-1

來源:互聯網
上載者:User

標籤:pos   條件   集合   div   except   rgs   概念   owa   abc   

博文重點:

    學習目標:哪些記憶體需要回收

         什麼時候回收

            如何回收

    在基於概念討論的模型中,主要對Java堆和方法區進行討論。

    why?:一個介面中的多個實作類別需要的記憶體可能不一樣,一個方法中的多個分支需要的記憶體也可能不一樣。只有在程式運行期間才能知道會建立哪些對象,這部分記憶體的分配和回收都是動態,gc關注的就是這一塊記憶體。

 

哪些記憶體需要回收:

        判斷對象是否存活:

                引用計數演算法:對象中添加一個引用計數器,有一個地方引用它則計數器加1,引用失效時,減1。引用為0的對象就是不可使用的。

                  優點:實現簡單,判定效率高。

                  缺點:無法解決對象之間的循環參考,見代碼。

 1 public class ReferenceCountingGC { 2     public Object instance = null; 3  4     private static final int _1MB = 1024 * 1024; 5  6     private byte[] bigSize = new byte[2 * _1MB]; 7  8     public static void testGC() { 9         ReferenceCountingGC objA = new ReferenceCountingGC();10         ReferenceCountingGC objB = new ReferenceCountingGC();11         objA.instance = objB;12         objB.instance = objA;13         14           15         objA = null;16         objB = null;17         18         // 雖然引用計數都為1,但記憶體還是被回收了,說明採用的不是引用計數演算法19         System.gc();20     }21 22     public static void main(String[] args) {23         testGC();24     }25 }            
View Code

 

                可達性分析演算法:思路,選擇一系列稱為"GC Roots"的對象作為起始點,從這些節點向下搜尋,走過的路就稱為引用鏈。如果一個對象無法通過引用鏈到達"GC roots",則證明該對象不可用,則可被回收。

                  可作為GC Roots的對象:虛擬機器棧中引用的對象,方法區類靜態屬性引用的對象,方法區中常量引用的對象,Nativa方法中引用的對象。 todo:理解gc roots

 

    引用:

      todo:各種應用情境

      引用細化定義:當記憶體空間還足夠,則能保留在記憶體中。如果記憶體空間進行垃圾收集之後還是非常緊張,則拋棄這些對象。

      基於這樣的需求,擴充了引用的概念。

      強引用:只要強引用存在,就永遠不會被gc。eg. Object obj = new Object();

 

      軟引用:記憶體充足時不會回收,不足時被回收。jvm將這個軟引用加入到與之關聯的引用隊列

      弱引用:無論記憶體是否充足,都會進行回收。jvm將這個弱引用加入到與之關聯的引用隊列

      虛引用:

    

    對象的兩次標記:如果對象在進行第一次可達性分析之後,沒有到gc roots到引用鏈,則進行第一次標記。並進入第一次自救過程,如果該對象重寫了finalize()方法時 && finalize()方法沒有被虛擬機器調用過,則會執行finalize()方法進行自救過程,將該對象放入到一個F-Queue到隊列中,由虛擬機器自動建立的,低優先順序的Finalize線程去執行(但是不保證會等待方法運行結束,為了效率考慮)。如果在finalize()方法中將該對象的引用賦值給了類變數或成員變數,重建立立起了可達關係,則在該第二次標記過程會被移出"即將回收"集合,自救成功,但要注意,這樣的自救只能執行一次。

    

 1 public class FinalizeEscapeGC { 2     public static FinalizeEscapeGC SAVE_HOOK = null; 3     public void isAlive() { 4         System.out.println("yes , i am still alive"); 5     } 6  7     @Override 8     protected void finalize() throws Throwable { 9         System.out.println("finalize method excute!");10         FinalizeEscapeGC.SAVE_HOOK = this;11     }12 13     public static void main(String[] args) throws InterruptedException {14         SAVE_HOOK = new FinalizeEscapeGC();15 16         // 第一次拯救自己成功17         SAVE_HOOK = null;18         System.gc();19 20         Thread.sleep(500);21         if(SAVE_HOOK != null) {22             SAVE_HOOK.isAlive();23         } else {24             System.out.println("dead");25         }26 27         // 第二次拯救自己失敗,只能執行一次28         SAVE_HOOK = null;29         System.gc();30 31         Thread.sleep(500);32         if(SAVE_HOOK != null) {33             SAVE_HOOK.isAlive();34         } else {35             System.out.println("dead");36         }37     }38 }
View Code

 

    方法區(永久代)的回收:主要回收廢棄常量和無用類。

                廢棄常量:eg:"abc"存在常量池中,但沒有其它地方引用這個常量,類,方法,欄位的符號引用也和這個類似。

                無用類:該類所有執行個體已被回收

                    載入該類的ClassLoader已被回收

                    對應的Class對象沒有被引用,無法在其它地方通過反射訪問該類的方法。

                      滿足了這些條件的類可以被回收,是否進行回收,取決於我們對虛擬機器的參數設定情況。

                使用情境:在大量使用反射,動態代理,CGLib等頻繁定義自ClassLoader的情境都需要虛擬機器具備類卸載的功能

 

深入理解java虛擬機器---垃圾收集器和分配策略-1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.