天天看點

JVM垃圾回收_1 . 如何判斷對象可以回收(五種引用)

如何判斷對象可以回收

引用計數法

弊端:循環引用時,兩個對象的計數都為1,導緻兩個對象都無法被釋放

JVM垃圾回收_1 . 如何判斷對象可以回收(五種引用)

可達性分析算法

  • JVM中的垃圾回收器通過可達性分析來探索所有存活的對象
  • 掃描堆中的對象,看能否沿着GC Root對象為起點的引用鍊找到該對象,如果找不到,則表示可以回收
  • 可以作為GC Root的對象
    • 虛拟機棧(棧幀中的本地變量表)中引用的對象。
    • 方法區中類靜态屬性引用的對象
    • 方法區中常量引用的對象
    • 本地方法棧中JNI(即一般說的Native方法)引用的對象

五種引用

JVM垃圾回收_1 . 如何判斷對象可以回收(五種引用)
強引用

隻有GC Root都不引用該對象時,才會回收強引用對象

  • 如上圖B、C對象都不引用A1對象時,A1對象才會被回收
軟引用

當GC Root指向軟引用對象時,在記憶體不足時,會回收軟引用所引用的對象

  • 如上圖如果B對象不再引用A2對象且記憶體不足時,軟引用所引用的A2對象就會被回收

軟引用的使用

public class Demo1 {
	public static void main(String[] args) {
		final int _4M = 4*1024*1024;
		//使用軟引用對象 list和SoftReference是強引用,而SoftReference和byte數組則是軟引用
		List<SoftReference<byte[]>> list = new ArrayList<>();
		SoftReference<byte[]> ref= new SoftReference<>(new byte[_4M]);
	}
}
           

如果在垃圾回收時發現記憶體不足,在回收軟引用所指向的對象時,軟引用本身不會被清理

如果想要清理軟引用,需要使用引用隊列

public class Demo1 {
	public static void main(String[] args) {
		final int _4M = 4*1024*1024;
		//使用引用隊列,用于移除引用為空的軟引用對象
		ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
		//使用軟引用對象 list和SoftReference是強引用,而SoftReference和byte數組則是軟引用
		List<SoftReference<byte[]>> list = new ArrayList<>();
		SoftReference<byte[]> ref= new SoftReference<>(new byte[_4M]);

		//周遊引用隊列,如果有元素,則移除
		Reference<? extends byte[]> poll = queue.poll();
		while(poll != null) {
			//引用隊列不為空,則從集合中移除該元素
			list.remove(poll);
			//移動到引用隊列中的下一個元素
			poll = queue.poll();
		}
	}
}
           

**大概思路為:**檢視引用隊列中有無軟引用,如果有,則将該軟引用從存放它的集合中移除(這裡為一個list集合)

弱引用

隻有弱引用引用該對象時,在垃圾回收時,無論記憶體是否充足,都會回收弱引用所引用的對象

  • 如上圖如果B對象不再引用A3對象,則A3對象會被回收

弱引用的使用和軟引用類似,隻是将 SoftReference 換為了 WeakReference

虛引用

當虛引用對象所引用的對象被回收以後,虛引用對象就會被放入引用隊列中,調用虛引用的方法

  • 虛引用的一個展現是釋放直接記憶體所配置設定的記憶體,當引用的對象ByteBuffer被垃圾回收以後,虛引用對象Cleaner就會被放入引用隊列中,然後調用Cleaner的clean方法來釋放直接記憶體
  • 如上圖,B對象不再引用ByteBuffer對象,ByteBuffer就會被回收。但是直接記憶體中的記憶體還未被回收。這時需要将虛引用對象Cleaner放入引用隊列中,然後調用它的clean方法來釋放直接記憶體
終結器引用

所有的類都繼承自Object類,Object類有一個finalize方法。當某個對象不再被其他的對象所引用時,會先将終結器引用對象放入飲用隊列中,然後根據終結器引用對象找到它所引用的對象,然後調用該對象的finalize方法。調用以後,該對象就可以被垃圾回收了

  • 如上圖,B對象不再引用A4對象。這是終結器對象就會被放入引用隊列中,引用隊列會根據它,找到它所引用的對象。然後調用被引用對象的finalize方法。調用以後,該對象就可以被垃圾回收了
引用隊列
  • 軟引用和弱引用可以配合引用隊列
    • 在弱引用和虛引用所引用的對象被回收以後,會将這些引用放入引用隊列中,友善一起回收這些軟/弱引用對象
  • 虛引用和終結器引用必須配合引用隊列
    • 虛引用和終結器引用在使用時會關聯一個引用隊列