1. 程式人生 > 實用技巧 >強軟弱虛四大引用

強軟弱虛四大引用

1.強引用

當記憶體不足,JVM開始垃圾回收,對於強引用的物件,就算是出現了OOM也不會對該物件進行回收,死都不收。

強引用是我們最常見的普遍物件引用,只要還有強引用指向一個物件,就能表明物件還活著,垃圾收集器不會碰這種物件。在JAVA最常見的就是強引用,把一個物件賦給一個引用變數就是一個強引用。當一個物件被強引用變數引用時,它處於可達狀態,它是不可能被垃圾回收機制回收的,即使該物件以後永遠都不會被用到JVM也不會回收,因此強引用時造成Java記憶體洩漏的主要原因之一。

對於一個普通的物件,如果沒有其他的引用關係,只要超過了引用的作用域或者顯式地將相應(強)引用複製為null,一版認為就是可以背垃圾收集了。

public class StrongReferenceDemo {
    public static void main(String []args) {
        Object obj1 = new Object(); //這樣定義預設是強引用
        Object obj2 = obj1;
        obj1 = null;
        System.gc();
        System.out.println(obj1);
        System.out.println(obj2);
    }
}


2.軟引用

軟引用是一種相對強引用弱化了一些的引用,需要用java.lang.ref.SoftReference類來實現,可以讓物件豁免一些垃圾收集,對於只有軟引用的物件來說,

當系統記憶體充足時它不會被回收,當系統記憶體不足時它會被回收。

軟引用通常用在對記憶體敏感的程式中,比如快取記憶體就有用到軟引用,記憶體夠用的時候就保留,不夠用就回收!

-Xms5m -Xmx5m -XX:+PrintGCDetails //設定引數

public class SoftReferenceDemo {
    public static void main(String []args) {
        Object o1 = new Object();
        SoftReference<Object> softReference = new SoftReference<Object>(o1);
        System.
out.println(o1); System.out.println(softReference.get()); o1 = null; System.gc(); try { byte[] bytes = new byte[30*1024*1024]; } finally { System.out.println(o1); System.out.println(softReference.get()); } } }


3.弱引用

弱引用需要用java.lang.ref.WeakReference類來實現,它比軟引用的生存區更短。

對於只有弱引用的物件來說,只要垃圾回收機制一執行,不管JVM的記憶體空間是否足夠,都會回收該物件佔用的記憶體。

public class WeakReferenceDemo {
    public static void main(String[] args) {
        Object o1 = new Object();
        WeakReference<Object> weakReference = new WeakReference<Object>(o1);
        System.out.println(o1);
        System.out.println(weakReference.get());

        o1 = null;
        System.gc();
        System.out.println("----------------------------");
        System.out.println(o1);
        System.out.println(weakReference.get());
    }
}


public class HashMapDemo {

    public static void main(String []args) {
        myHashMap();
    }

    private static void myHashMap() {
        HashMap<Integer,String> map = new HashMap<>();
        Integer key = new Integer(1);
        String value = "hashMap";
        map.put(key,value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);
    }

}

public class WeakHashMapDemo {

    public static void main(String []args) {
        myWeakHashMap();
    }

    private static void myWeakHashMap() {
        WeakHashMap<Integer,String> map = new WeakHashMap<>();
        Integer key = new Integer(2);
        String value = "weakHashMap";
        map.put(key,value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);
    }

}


4.虛引用

虛引用需要java.lang.ref.PhantomReference類來實現。

顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定物件的生命週期。

如果一個物件僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時間都可能被垃圾回收

器回收,它不能單點使用也不能通過它訪問物件,虛引用必須和引用佇列(ReferenceQueue)聯合使用。

虛引用的主要作用是跟蹤物件被垃圾回收的狀態,僅僅是提供了一種確保物件被finalize以後,做某些事情的機制。PhantomReference的get方法總是返回null,因此無法訪問對應的引用物件,其意義在於說明一個物件已經進入了finalization階段,可以被gc回收,用來實現比finalization機制更靈活的回收操作。

換句話說,設定虛引用關聯的唯一目的,就是在這個物件被收集器回收的時候收到一個系統通知或者後續新增進一步的處理。Java技術允許使用fianlize()方法在垃圾收集器將物件從記憶體中清除出去之前做必要的清理工作

public class PhantomReferenceDemo {

    public static void main(String []args) throws Exception {
        Object o1 = new Object();
        ReferenceQueue<Override> referenceQueue = new ReferenceQueue<>();
        PhantomReference<Object> phantomReference = new PhantomReference(o1,referenceQueue);
        System.out.println(o1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("-----------------");
        o1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(o1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

    }
}