Java中的垃圾回收與對象生命週期

1. 垃圾回收

   垃圾回收是Java程序設計中內存管理的核心概念,JVM的內存管理機制被稱爲垃圾回收機制。

  一個對象建立後被放置在JVM的堆內存中,當永遠再也不引用這個對象時,它將被JVM在堆內存中回收。被建立的對象不能再生,同時也沒有辦法經過程序語句釋放它們。即當對象在JVM運行空間中沒法經過根集合到達(找到)時,這個對象被稱爲垃圾對象。根集合是由類中的靜態引用域與本地引用域組成的。JVM經過根集合索引對象。

    在作Java應用開發時常常會用到由JVM管理的兩種類型的內存:堆內存和棧內存。簡單來說,堆內存主要用來存儲程序在運行時建立或實例化的對象與變量。例如經過new關鍵字建立的對象。而棧內存則是用來存儲程序代碼中聲明爲靜態或非靜態的方法。


(1) 堆內存

    堆內存在JVM啓動的時候被建立,堆內存中所存儲的對象能夠被JVM自動回收,不能經過其餘外部手段回收,也就是說開發人員沒法經過添加相關代碼的手段來回收堆內存中的對象。堆內存一般狀況下被分爲兩個區域:新對象區域與老對象區域。

    新對象區域:又可細分爲三個小區域:伊甸園區域、From區域與To區域。伊甸園區域用來保存新建立的對象,它就像一個堆棧,新的對象被建立,就像指向該棧的指針在增加同樣,當伊甸園區域中的對象滿了以後,JVM系統將要作到可達性測試,主要任務是檢測有哪些對象由根集合出發是不可達的,這些對象就能夠被JVM回收,而且將全部的活動對象從伊甸園區域拷貝到To區域,此時一些對象將發生狀態交換,有的對象就從To區域被轉移到From區域,此時From區域就有了對象。上面對象遷移的整個過程,都是由JVM控制完成的。

    老對象區域:在老對象區域中的對象仍然會有一個較長的生命週期,大多數的JVM系統垃圾對象,都是源於"短命"對象,通過一段時間後,被轉入老對象區域的對象,就變成了垃圾對象。此時,它們都被打上相應的標記,JVM系統將會自動回收這些垃圾對象,建議不要頻繁地強制系統做垃圾回收,這是由於JVM會利用有限的系統資源,優先完成垃圾回收工做,致使應用沒法快速地響應來自用戶端的請求,這樣會影響系統的總體性能。


(2) 棧內存

    堆內存主要用來存儲程序在運行時建立或實例化的對象與變量。例如經過new關鍵字建立的對象。而棧內存則是用來存儲程序代碼中聲明爲靜態或非靜態的方法。

2. JVM中對象的生命週期

   在JVM運行空間中,對象的整個生命週期大體能夠分爲7個階段:
   建立階段;
   應用階段;
   不可視階段;
   不可到達階段;
   可收集階段;
   終結階段;
   釋放階段
 

   上面這7個階段,構成了JVM中對象的完整的生命週期。


   (1) 建立階段

       在對象的建立階段,系統主要經過下面的步驟,完成對象的建立過程:
    
       <1> 爲對象分配存儲空間;
       <2> 開始構造對象;
       <3> 從超類到子類對static成員進行初始化;
       <4> 超類成員變量按順序初始化,遞歸調用超類的構造方法;
       <5> 子類成員變量按順序初始化,子類構造方法調用。

       在建立對象時應注意幾個關鍵應用規則:
      
       <1> 避免在循環體中建立對象,即便該對象佔用內存空間不大。
       <2> 儘可能及時使對象符合垃圾回收標準。好比 myObject = null。
       <3> 不要採用過深的繼承層次。
       <4> 訪問本地變量優於訪問類中的變量。
java

 (2) 應用階段

       在對象的引用階段,對象具有以下特徵:

      <1> 系統至少維護着對象的一個強引用(Strong Reference);
      <2> 全部對該對象的引用所有是強引用(除非咱們顯示地適用了:軟引用(Soft Reference)、弱引用(Weak Reference)或虛引用(Phantom Reference)).


      強引用(Strong Reference):是指JVM內存管理器從根引用集合出發遍歷堆中全部到達對象的路徑。當到達某對象的任意路徑都不含有引用對象時,這個對象的引用就被稱爲強引用。

       軟引用(Soft Reference):軟引用的主要特色是有較強的引用功能。只有當內存不夠的時候,纔回收這類內存,所以內存足夠時它們一般不被回收。另外這些引用對象還能保證在Java拋出OutOfMemory異常以前,被設置爲null。它能夠用於實現一些經常使用資源的緩存,實現Cache功能,保證最大限度地使用內存你而不引發OutOfMemory。算法

 

下面是軟引用的實現代碼:緩存

 

                                import java.lang.ref.SoftReference;安全

                                ...函數

                                 

                                A a = new A();性能

                                ...測試

 

                                // 使用aspa

                                ...線程

                                  

                                // 使用完了a, 將它設置爲soft引用類型,而且釋放強引用設計

                                SoftReference sr = new SoftReference(a);

                                a = null;

                                ...

 

                                // 下次使用時

                    if (sr != null) {

                    a = sr.get();

                } else {

                    // GC因爲低內存,已釋放a,所以須要從新裝載

                                    a = new A();

                    sr = new SoftReference(a);

                }

 

 軟引用技術的引進使Java應用能夠更好地管理內存,穩定系統,防止系統內存溢出,避免系統崩潰。所以在處理一些佔用內存較大且生命週期較長,但使用並不繁地對象時應儘可能應用該技術。提升系統穩定性。
            
                                     
       弱引用(Weak Reference):弱應用對象與軟引用對象的最大不一樣就在於:GC在進行垃圾回收時,須要經過算法檢查是否回收Soft應用對象,而對於Weak引用,GC老是進行回收。Weak引用對象更容易、更快地被GC回收。Weak引用對象經常用於Map結構中。

import java.lang.ref.WeakReference;  

4.                               ...  

5.                                 

6.                               A a = new A();  

7.                               ...  

8. 

9.                               // 使用a  

10.                               ...  

11.                                  

12.                               // 使用完了a, 將它設置爲Weak引用類型,而且釋放強引用  

13.                               WeakReference wr = new WeakReference(a);  

14.                               a = null;  

15.                               ...  

16. 

17.                               // 下次使用時  

18.                if (wr != null) {  

19.                    a = wr.get();  

20.            } else {  

21.                                   a = new A();  

22.                wr = new WeakReference(a);  

23.            } 

 虛引用(Phantom Reference): 虛引用的用途較少,主要用於輔助finalize函數的使用。

虛引用(Phantom Reference)對象指一些執行完了finalize函數,併爲不可達對象,可是尚未被GC回收的對象。這種對象能夠輔助finalize進行一些後期的回收工做,咱們經過覆蓋了Refernce的clear()方法,加強資源回收機制的靈活性。

      
       在實際程序設計中通常不多使用弱引用和虛引用,是用軟引用的狀況較多,由於軟引用能夠加速JVM對垃圾內存的回收速度,能夠維護系統的運行安全,防止內存溢出(OutOfMemory)等問題的產生。


    (3) 不可視階段
         當一個對象處於不可視階段,說明咱們在其餘區域的代碼中已經不能夠在引用它,其強引用已經消失,例如,本地變量超出了其可視
的範圍。 

     

1.try {  

2.            Object localObj = new Object();  

3.     localObj.doSomething();  

4.      } catch (Exception e) {  

5.          e.printStackTrace();  

6.      }  

7

8.      if (true) {  

9.    // 此區域中localObj 對象已經不可視了, 編譯器會報錯。  

10.    localObj.doSomething();  

11.      } 

 (4) 不可到達階段
       處於不可達階段的對象在虛擬機的對象引用根集合中再也找不到直接或間接地強引用,這些對象通常是全部線程棧中的臨時變量。全部已經裝載的靜態變量或者是對本地代碼接口的引用。


   (5) 可收集階段、終結階段與釋放階段        當一個對象處於可收集階段、終結階段與釋放階段時,該對象有以下三種狀況:        <1> 回收器發現該對象已經不可達。        <2> finalize方法已經被執行。        <3> 對象空間已被重用。

相關文章
相關標籤/搜索