Java虛擬機採用可達性分析演算法來判斷對象是否可以回收。可達性分析演算法通過一系列的GC Roots對象作為起始點,向下搜索走過的路徑稱引用鏈,當一個對象到GC Roots沒有任何的引用鏈時,證明對象是不可用的。 Java中,可作為GC Roots的對象: 虛擬機棧中引用的對象 ...
Java虛擬機採用可達性分析演算法來判斷對象是否可以回收。可達性分析演算法通過一系列的GC Roots對象作為起始點,向下搜索走過的路徑稱引用鏈,當一個對象到GC Roots沒有任何的引用鏈時,證明對象是不可用的。
Java中,可作為GC Roots的對象:
- 虛擬機棧中引用的對象
- 本地方法棧的JNI引用的對象
- 方法區靜態屬性引用的對象
- 方法區常量引用的對象
Java對引用進行了擴充,分為強引用、軟引用、弱引用、虛引用四種。
- 強引用:(StrongReference)
強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不回收。當記憶體空間不足,Java虛擬機寧願拋出OutOfMemoryError
錯誤,使程式異常終止,也不會靠隨意回收具有強引用的對象來解決記憶體不足的問題。
// 強引用的示例
String string = "hello";
- 軟引用:(SoftReference)
如果一個對象只具有軟引用,則只有在記憶體空間不足的時,才會回收。可以和一個引用隊列聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。
// 軟引用的示例
SoftReference<String> softRefString = new SoftReference<>("hello", queue);
- 弱引用:(WeakReference)
弱引用與軟引用的區別在於:弱引用的對象擁有更短暫的生命周期。垃圾回收線程一旦發現了具有弱引用的對象,不管當前記憶體空間足夠與否,都會回收它的記憶體。不過,由於垃圾回收器是一個優先順序很低的線程,因此不一定會很快發現那些只具有弱引用的對象。可以和一個引用隊列聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。
// 弱引用的示例
WeakReference<String> weakRefString = new WeakReference<>("hello", queue);
- 虛引用:(PhantomReference)
虛引用並不會決定對象的生命周期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。 必須和引用隊列 聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的記憶體之前,把這個虛引用加入到與之關聯的引用隊列中。
// 虛引用的示例
ReferenceQueue<String> queue = new ReferenceQueue<>();
PhantomReference<String> phanRefString = new PhantomReference<>("hello", queue);
參考資料:《深入理解Java虛擬機(第二版)》《Java虛擬機規範(Java SE 8版)》