【JVM】如何了解強引用、軟引用、弱引用、虛引用?
整體架構
強引用
強引用是預設支援,當記憶體不足的時候,JVM開始垃圾回收,對于強引用的對象,就算是出現了OOM也不會回收對象。
強引用是最常見的普通對象引用,隻要還有強引用指向對象,對象就存活,垃圾回收器不會處理存活對象。一般把一個對象賦給一個引用變量,這個引用變量就是強引用。當一個對象被強引用變量所引用,它就處于可達狀态,是不會被垃圾回收的,即使之後都不會再用到了,也不會回收。是以強引用是造成Java記憶體洩漏的主要原因之一。
關于Java記憶體洩漏的詳細内容,可以參考這篇部落格:
https://blog.csdn.net/m0_38110132/article/details/81986334。
對于一個普通對象,如果沒有其他引用關系,隻要超過了引用的作用域或者顯式地将相應的強引用指派為null,一般認為就是可以被垃圾回收了。(具體的回收時機看垃圾回收政策)
下例中,b就是強引用。
1 public static void main(String[] args) {
2 Object a = new Object();
3 Object b = a;
4 a = null;
5 System.out.println(b);//java.lang.Object@4554617c
6 }
軟引用
軟引用是一種相對強引用弱化了一些的引用,用java.lang.ref.SoftReference實作,可以讓對象豁免一些垃圾收集。當系統記憶體充足的時候,不會被回收;當系統記憶體不足的時候,會被回收。
軟引用一般用于對記憶體敏感的程式中,比如高速緩存。
1 import java.lang.ref.SoftReference;
2
3 public class SoftReferenceDemo {
4 public static void main(String[] args) {
5 Object a = new Object();
6 SoftReference
使用場景
一個應用需要讀取大量的本地圖檔,如果每次讀取都從硬碟讀取會嚴重影響性能,如果一次性全部加載到記憶體,記憶體可能會溢出。
可以使用軟引用解決這個問題,使用一個HashMap來儲存圖檔路徑和圖檔對象管理的軟引用之間的映射關系,記憶體不足時,JVM會自動回收緩存圖檔對象的占用空間,有效地避免了OOM(Out Of Memory)問題。
Map> imageCache = new HashMap>
弱引用
弱引用需要用java.lang.ref.WeakReference實作,它比軟引用的生存期更短,對于弱引用的對象來說,隻要垃圾回收機制一運作,不管JVM的記憶體空間是否夠,都會回收該對象的占用記憶體。
1 import java.lang.ref.WeakReference;
6 WeakReference
關于WeakHashMap
1 public static void weakHashMapTest() {
2 Integer key = new Integer(1);
3 String value = "李四";
4 Map weakHashMap = new WeakHashMap();
5 weakHashMap.put(key, value);
6 System.out.println(weakHashMap);//{1=李四}
7 key = null;
8 System.gc();
9 System.out.println(weakHashMap);//{}
10 }
11
12 public static void hashMapTest() {
13 HashMap map = new HashMap<>();
14 Integer key = 1;
15 String value = "張三";
16 map.put(key,value);
17 System.out.println(map);//{1=張三}
18 key = null;
19 System.gc();
20 System.out.println(map);//{1=張三}
21 }
在HashMap中,鍵被置為null,喚醒gc後,不會垃圾回收鍵為null的鍵值對。但是在WeakHashMap中,鍵被置為null,喚醒gc後,鍵為null的鍵值對會被回收。
虛引用
虛引用要通過java.lang.ref.PhantomReference類來實作,虛引用不會決定對象的生命周期,如果一個對象隻有虛引用,就相當于沒有引用,在任何時候都可能會被垃圾回收器回收。它不能單獨使用也不能通路對象,虛引用必須和引用隊列聯合使用。
虛引用的主要作用是跟蹤對象被垃圾回收的狀态,僅僅是提供一種確定對象被finalize以後,做某些事情的機制。
PhantomReference的get方法總是傳回null,是以無法通路對應的引用對象,設定虛引用關聯唯一的目的是在對象被收集器回收的時候收到一個系統通知,或者後續添加進一步的處理。Java允許使用finalize()方法在垃圾回收器将對象從記憶體中清理出去之前做一些必要的清理工作。【例如實作一個監控對象的通知機制】
引用隊列
WeakReference和ReferenceQueue的聯合使用效果:
1 public static void weakReferenceTest() {
2 Object a = new Object();
3 ReferenceQueue
PhantomReference和ReferenceQueue的聯合使用效果:
1 public static void phantomReferenceTest() {
總結
強引用:不回收。
軟引用:記憶體不夠就回收。
弱引用:一定回收。
虛引用:一定回收,get出來就是null,引用形同虛設,主要和引用隊列聯合使用,在finalize之前會被放到引用隊列中。
與根對象沒有引用關系的:引用不可達,一定回收。
原文位址
https://www.cnblogs.com/xdcat/p/13024683.html