天天看點

強-軟-弱-虛引用1、強引用 Reference2、軟引用  SoftReference3、弱引用 WeakReference4、 虛引用 PhantomReference5、小結

目錄

1、強引用 Reference

2、軟引用  SoftReference

3、弱引用 WeakReference

4、 虛引用 PhantomReference

5、小結

前言         如果reference類型的資料中存放的數值是另外一塊記憶體的起始位址,就稱這塊記憶體代表着一個引用。為了更好的控制對象的生命周期,提高記憶體使用率,JDK1.2 之後,java擴充了引用的概念,将引用分為 強引用/軟引用/弱引用/和虛引用四種。

  • 強引用(Strong Reference) :隻要對象可達就不會被回收,哪怕抛出OOM
  • 軟引用(Soft Reference):記憶體不足的時候才回收
  • 弱引用(Weak Reference):下次gc的時候就回收;
  • 虛引用(Phantom Reference):跟蹤對象什麼時候被回收

1、強引用 Reference

  • 類似于"Object obj = new Object()"這類的引用,隻要垃圾強引用存在,垃圾回收器就不會回收掉被引用的對象;

示例:

//強引用
public class   {
    static Object obj = new Object();
    public static void main(String[] args) {
        Object obj2 = new Object();//一樣不會被回收
        Object obj1 = obj;
        obj = null;  //注意引用隻是一個位址變量,obj=null, 但是 obj1 = new Object()還存在引用
        System.gc();
        System.out.println("gc 後:obj1-" + obj1);
        System.out.println("gc 後:obj-" + obj);
    }
}
           

回收的情況:

  • 1、作用域結束;
  • 2、不可達,複制為null;

2、軟引用  SoftReference

  • 當記憶體不夠時回收

示例:

public class SoftReferenceTest {
    public static void main(String[] args) {
        Object obj = new Object();
        //在程式發生oom前才會被回收;記憶體不足的時候才會被回收
        //并且優先回收長時間空閑的對象
        //适合非必須大對象的緩存;
        SoftReference softReference = new SoftReference(obj);
        System.out.println(softReference.get());
    }
}
           

3、弱引用 WeakReference

  • 強度比軟引用更弱,被弱引用關聯的對象隻能存活到下一次垃圾回收gc之前,當發生gc,無論目前的記憶體是否充足,都會gc回收掉弱引用關聯的對象;
強-軟-弱-虛引用1、強引用 Reference2、軟引用  SoftReference3、弱引用 WeakReference4、 虛引用 PhantomReference5、小結

使用示例:

@Data
public class Orange {
    private String name;

    public Orange(String name) {
        this.name = name;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized~ ");
        super.finalize();
    }
}
public class WeakOrange extends WeakReference<Orange> {

    public WeakOrange(Orange referent) {
        super(referent);
    }
}

public class WeakReferenceTest {

    public static void main(String[] args) {
        Orange orange = new Orange("king");             //強引用
        String str = "king-zz";
        WeakOrange weakOrange = new WeakOrange(orange); //弱引用
        orange = null;
        WeakOrange weakOrange = new WeakOrange(str);    //弱引用-str 此時str不會被回收,因為str在常量池中,gc不會清理常量池
        str = null;
        System.out.println("gc前 " + weakOrange.get());
        System.gc(); // 發生gc
        try {
            sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("gc 後:" +  weakOrange.get());

    }
}
           

運作結果result:

gc前 Orange(name=king)
finalized~
gc 後:null
           

4、 虛引用 PhantomReference

  • 引用基本不影響什麼,做個标記,在垃圾回收前,處理一些事情。

執行個體: 跟蹤對象什麼時候會回收,隻有在gc的時候,才會在虛引用隊列裡取到該值,判斷回收前需要做什麼。

public class PhantomRef {

    public static void main(String[] args) throws InterruptedException {

        Object obj = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        //todo 必須是對象和隊列一起使用才OK;
        PhantomReference phantomReference = new PhantomReference(obj, queue);
        //todo 這裡擷取的值永遠為空,隻有在gc的時候,才會在隊列的取到這個對象的值,做一些資源的關閉清理;
        System.out.println("phantomReference1 " + phantomReference.get());  //null
        obj = null;
        System.gc(); //gc前會将該對象放入到隊列中,然後處理完後再回收
        System.out.println("phantomReference2 " + phantomReference.get());
        sleep(1000);
        System.out.println("queue.poll " + queue.poll());
    }
}
           

5、小結

    引用讓我們更好的控制對象的生命周期,更高效的利用記憶體,防止記憶體洩漏。       水滴石穿,積少成多。學習筆記,内容簡單,用于複習,梳理鞏固。