java中的四種引用——強、軟、弱、虛

一、強引用

強引用比較好理解,我們編程中絕大部分對象都是強引用,在GC過程中,如果存在強引用對象,即便發(fā)生OOM,也不會被回收

Object m = new Object();

二、軟引用

在堆內(nèi)存不足時,jvm的GC會回收軟引用對象

public class SoftReferenceTest {
    public static void main(String[] args) {
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());

        byte[] b = new byte[1024 * 1024 * 15];
        System.out.println(m.get());
    }
}

上述代碼在內(nèi)存中的引用關(guān)系如下圖所示



假如我們指定-Xmx20M,然后運行

[B@2503dbd3
[B@2503dbd3
null

從運行結(jié)果可以看出,第一次和第二次輸入對象不為空,即便中間發(fā)生了一次gc,第二次依然不為空,是因為內(nèi)存足夠,所以不會被回收,但是當?shù)谌蝞ew一個15M的對象時,總空間15+10=25M,超出堆內(nèi)存總大小(20M),這時jvm會回收調(diào)軟引用對象。

軟引用的使用場景:緩存(比如緩存一些圖片文件)

三、弱引用

把上面代碼稍作修改,將軟引用改為弱引用,其他保持不變

public class WeakReferenceTest {
    public static void main(String[] args) {
        WeakReference<byte[]> m = new WeakReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());

        byte[] b = new byte[1024 * 1024 * 15];
        System.out.println(m.get());
    }
}

運行結(jié)果

[B@2503dbd3
null
null

從運行結(jié)果可以看出,第二次輸出時,即便內(nèi)存足夠,依然會被回收。

結(jié)論:垃圾回收器會直接回收弱引用對象,和軟引用的區(qū)別就是不管內(nèi)存是否充裕都會被回收。

ThreadLocal就是用到了弱引用技術(shù),關(guān)于ThreadLocal可以參見另一篇博文
ThreadLocal

四、虛引用

public class PhantomReferenceTest {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
    public static void main(String[] args) {
        PhantomReference<M> pr = new PhantomReference<>(new M(), QUEUE);
        //虛引用輸出為空
        System.out.println(pr.get());
    }
}

java官方的解釋:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
虛引用指向的對象有可能會被重新訪問到,常用于對象死亡后的清理操作。


在NIO場景中,堆內(nèi)存中的對象有可能會訪問堆外內(nèi)存的對象,當堆內(nèi)存被GC回收時,堆外內(nèi)存也應(yīng)該釋放,JVM是怎么知道堆外內(nèi)存是否可回收呢,所以java提供了一種鉤子機制,這種機制就是虛引用。

應(yīng)用場景:管理直接內(nèi)存(堆外內(nèi)存)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容