JVM學習之引用類型

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_34560242/article/details/81044700

Java引入類型

  • 強引用:當內存不足的時候,JVM寧可出現OutOfMemoryError,也不會將內存回收。

    強引用是JVM默認的支持模式,即:在引用期間,如果該堆內存被棧內存所指向,那麼該對象無法被GC回收,如果出現內存空間不足,就會拋出 “OutOfMemoryError”。

    public static void main(String[] args) {
        Object o = new Object(); // 強引用
        Object ref = o; // 引用傳遞
        o = null; // 斷開一個引用
        System.gc(); // 手動垃圾回收
        System.out.println(ref);
    }
    
    輸出:
    java.lang.Object@3cd1a2f1
  • 軟引用:內存不足的時候,進行對象的回收,往往用於高速緩存。

    在許多的開源組件之中,往往會使用軟引用作爲緩存組件出現,最大的特點就是:內存空間充足時不回收,內存空間不足時回收。

    // 內存充足
    public static void main(String[] args) {
        Object o = new Object();
        SoftReference softReference = new SoftReference(o); // 軟引用
        o = null; // 使new Object() 只維護一個軟引用
        System.gc(); // 垃圾回收
        System.out.println("軟引用:" + softReference.get());
    }
    
    輸出:
    軟引用:java.lang.Object@3cd1a2f1
    
    /******************************************************/
    
    // 內存不足
    public static void main(String[] args) {
        Object o = new Object();
        SoftReference softReference = new SoftReference(o); // 軟引用
        o = null; // 使new Object() 只維護一個軟引用
        // 創造大量垃圾,觸發GC
        String str = "showSoftRef";
        try {
            for (int i = 0; i < 100; i++) {
                str += str;
                str.intern();
            }
        } catch (Throwable e) {
    
        }
        System.out.println("軟引用:" + softReference.get());
    }
    
    輸出:
    軟引用:null
  • 弱引用:不管內存是否緊張,只要有GC處理,就會被回收。弱引用需要使用的是Map接口的子類:java.util.WeakHashMap。

    public static void main(String[] args) {
        String hello = new String("hello");
        String world = new String("world");
        // 弱引用
        Map<String, String> map = new WeakHashMap<String, String>();
        map.put(hello, world);
        System.out.println(map);
        hello = null; //斷開強引用
        System.out.println(map);
        System.gc(); // 垃圾回收
        System.out.println(map);
    }
    
    輸出:
    {hello=world}
    {hello=world}
    {}
    
    /******************************************************/
    把上面的WeakHashMap替換成HashMap,輸出結果爲:
    {hello=world}
    {hello=world}
    {hello=world}
    
    // 因爲:HashMap是強引用,不會被回收
    // 爲什麼項目中不用WeakHashMap而頻繁使用HashMap呢?
    // 如果在項目中使用WeakHashMap,當一條線程在取數據的時候,另外一條線程在進行GC,這個容易丟失數據。
    
    /******************************************************/
    public static void main(String[] args) {
        Object o = new Object();
        WeakReference softReference = new WeakReference(o); // 弱引用
        o = null; // 使new Object() 只維護一個弱引用
        System.gc(); // 垃圾回收
        System.out.println("弱引用:" + softReference.get());
    }
    
    輸出:
    弱引用:null
  • 幽靈引用(虛引用):永遠無法從這個引用中取數據。

    所有保存在幽靈引用中的數據都不會真正的保留。

    public static void main(String[] args) throws InterruptedException {
        Object o = new Object();
        ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
        PhantomReference softReference = new PhantomReference(o, queue); // 幽靈引用
        // 這裏沒有斷開強引用
        System.gc();
        System.out.println(softReference.get());
        System.out.println(queue.poll());
    }
    
    輸出:
    null
    null
  • 引用對列:保存準備被回收的對象。很多時候對象的回收掃描都要從根集合開始,那麼對於整個GC而言,要想確定哪些對象可以被回收,就必須確定好引用的強度這個也就是所謂的引用路徑設置。
    這裏寫圖片描述

    如果現在要找到對象5,很明顯:1 到 5 屬於 “強+軟”,2 到 5 屬於 “強+弱”;軟引用要比弱引用保存程度更強。這個時候對於對象的引用而言,如果要進行引用的關聯判斷,我們就必須找到強關聯。爲了避免非強引用對象帶來的內存引用問題,所以提供引用隊列的概念。

    如果在創建軟引用或者弱引用類型的時候使用引用隊列的方式,那麼這個對象被回收之後會自動保存在引用隊列之中。

    public static void main(String[] args) throws InterruptedException {
     Object o = new Object();
     ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); // 引用隊列
     WeakReference softReference = new WeakReference(o, queue); // 弱引用
     System.out.println(queue.poll());
     o = null; // 斷開強引用
     System.gc();
     Thread.sleep(100); // 等待對象被保存到引用隊列中
     System.out.println(queue.poll());
    }
    
    輸出:
    null
    java.lang.ref.WeakReference@3cd1a2f1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章