首頁  >  文章  >  Java  >  Java 詳解垃圾回收與物件生命週期

Java 詳解垃圾回收與物件生命週期

高洛峰
高洛峰原創
2017-01-17 15:50:541499瀏覽

Java 垃圾回收與物件生命週期詳解

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) 創建階段

       在物件的建立階段,系統主要透過下列的步驟,完成物件的建立流程:      

🠎       開始建構物件; 

       從超類別到子類別對static成員初始化; 

       超類別成員變數依序初始化,而遞歸呼叫超類別的建構方法; 

       子類別成員變數依序初始化,子類別建構方法調用。


     Sharp 

       盡量及時使對象符合垃圾回收標準。比如 myObject = null。 

       不要採用過深的繼承層次。 
       存取本地變數優於存取類別中的變數。

 (2) 應用階段

       在物件的引用階段,物件具備以下特徵:

      系統至少維持物件的一個強引用(Strong Reference); 🠎顯示地適用了:軟引用(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();
        ...
 
        // 使用a
        ...
          
        // 使用完了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;  
                ...  
                  
               A a = new A();  
               ...  
  
               // 使用a  
               ...  
                  
               // 使用完了a, 将它设置为Weak引用类型,并且释放强引用  
               WeakReference wr = new WeakReference(a);  
               a = null;  
                ...  
               // 下次使用时  
       if (wr != null) {  
         a = wr.get();  
      } else {  
                  a = new A();  
        wr = new WeakReference(a);  
    }

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

虛引用(Phantom Reference)物件指一些執行完了finalize函數,並為不可達對象,但是還沒有被GC回收的物件。這種物件可以輔助finalize進行一些後期的回收工作,我們透過涵蓋了Refernce的clear()方法,增強資源回收機制的彈性。

              在實際上設定中一般很少使用弱引用和虛引用,是用軟引用的情況較多,因為軟引用可以加速JVM對垃圾內存的回收速度,可以維護系統的運行安全,防止內存溢出( OutOfMemory)等問題的產生。

    (3) 不可視階段 

         當一個物件處於不可視覺階段,表示我們在其他區域的程式碼中已經不可以在引用它,其強引用已經消失,例如,本地變數超出了其視覺 的範圍。

try {  
      Object localObj = new Object();  
  localObj.doSomething();  
   } catch (Exception e) {  
     e.printStackTrace();  
   }  
  
   if (true) {  
  // 此区域中localObj 对象已经不可视了, 编译器会报错。  
  localObj.doSomething();  
   }

 (4) 不可到達階段 


       處於不可達階段的物件在虛擬機器的物件引用根集合中再也找不到直接或間接地強引用,這些物件一般是所有執行緒棧中的臨時變數。所有已經裝載的靜態變數或是對本地程式碼介面的參考。


   (5) 可收集階段、終結階段與釋放階段 

       當一個物件處於可收集階段、終端階段與釋放階段時,此物件有下列三種狀況:

.已經不可達。

       finalize方法已執行。

       物件空間已重複使用。 

謝謝閱讀,希望能幫助大家,謝謝大家對本站的支持!

更多Java 詳解垃圾回收與物件生命週期相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn