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
不要採用過深的繼承層次。
存取本地變數優於存取類別中的變數。
(2) 應用階段
在物件的引用階段,物件具備以下特徵:
系統至少維持物件的一個強引用(Strong Reference); 顯示地適用了:軟引用(Soft Reference)、弱引用(Weak Reference)或虛引用(Phantom Reference)).
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); }
弱引用(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); }
當一個物件處於不可視覺階段,表示我們在其他區域的程式碼中已經不可以在引用它,其強引用已經消失,例如,本地變數超出了其視覺 的範圍。
try { Object localObj = new Object(); localObj.doSomething(); } catch (Exception e) { e.printStackTrace(); } if (true) { // 此区域中localObj 对象已经不可视了, 编译器会报错。 localObj.doSomething(); }
(5) 可收集階段、終結階段與釋放階段
.已經不可達。
謝謝閱讀,希望能幫助大家,謝謝大家對本站的支持!
更多Java 詳解垃圾回收與物件生命週期相關文章請關注PHP中文網!