java的四種引用

無(wú)論是通過(guò)引用計(jì)數(shù)算法判斷對(duì)象的引用數(shù)量,還是通過(guò)可達(dá)性分析算法判斷對(duì)象是否引用鏈可達(dá),判定對(duì)象是否存活都和“引用”離不開(kāi)關(guān)系。

在JDK 1.2版之后,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用(Strongly Re-ference)、軟引用(Soft Reference)、弱引用(Weak Reference)和虛引用(Phantom Reference)4種,這4種引用強(qiáng)度依次逐漸減弱。

一、強(qiáng)引用

強(qiáng)引用是最傳統(tǒng)的“引用”的定義,是指在程序代碼之中普遍存在的引用賦值,即類似“Object obj=new Object()”這種引用關(guān)系。無(wú)論任何情況下,只要強(qiáng)引用關(guān)系還存在,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象。

二、軟引用

軟引用是用來(lái)描述一些還有用,但非必須的對(duì)象。只被軟引用關(guān)聯(lián)著的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常前,會(huì)把這些對(duì)象列進(jìn)回收范圍之中進(jìn)行第二次回收,如果這次回收還沒(méi)有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常。在JDK 1.2版之后提供了SoftReference類來(lái)實(shí)現(xiàn)軟引用。

應(yīng)用場(chǎng)景:緩存。

import java.lang.ref.SoftReference;

/**
 * @description: 軟引用
 * ·軟引用是用來(lái)描述一些還有用,但非必須的對(duì)象。只被軟引用關(guān)聯(lián)著的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)
 * 存溢出異常前,會(huì)把這些對(duì)象列進(jìn)回收范圍之中進(jìn)行第二次回收,如果這次回收還沒(méi)有足夠的內(nèi)存,
 * 才會(huì)拋出內(nèi)存溢出異常。在JDK 1.2版之后提供了SoftReference類來(lái)實(shí)現(xiàn)軟引用。
 *
 * 應(yīng)用場(chǎng)景:緩存
 *
 * @author:weirx
 * @date:2021/5/19 16:39
 * @version:3.0
 */
public class SoftReferenceTest {

    public static void main(String[] args) throws InterruptedException {
        SoftReference<byte[]> m = new SoftReference(new byte[1024 * 1024 * 10]);

        System.out.println(m.get());

        //第一次垃圾回收
        System.gc();
        Thread.sleep(1000);
        System.out.println(m.get());

        //分配一個(gè)強(qiáng)引用的byte,看看當(dāng)堆空間不足時(shí),是否會(huì)將軟引用回收。
        // 需要啟動(dòng)時(shí)將最大堆內(nèi)存設(shè)置為25M,當(dāng)內(nèi)存不足后發(fā)生第二次垃圾回收之后在獲取軟引用就是null。
        byte[] bytes = new byte[1024 * 1024 * 12];
        System.out.println(m.get());
    }
}

測(cè)試時(shí)需要指定啟動(dòng)內(nèi)存大?。?/p>

-Xmx25m

結(jié)果:

[B@6f75e721
[B@6f75e721
null

三、弱引用

弱引用也是用來(lái)描述那些非必須對(duì)象,但是它的強(qiáng)度比軟引用更弱一些,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集發(fā)生為止。當(dāng)垃圾收集器開(kāi)始工作,無(wú)論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉只被弱引用關(guān)聯(lián)的對(duì)象。在JDK 1.2版之后提供了WeakReference類來(lái)實(shí)現(xiàn)弱引用。

應(yīng)用:ThreadLocal;WeakHashMap。

import java.lang.ref.WeakReference;

/**
 * @description: 弱引用
 *
 * 弱引用也是用來(lái)描述那些非必須對(duì)象,但是它的強(qiáng)度比軟引用更弱一些,被弱引用關(guān)聯(lián)的對(duì)象只
 * 能生存到下一次垃圾收集發(fā)生為止。當(dāng)垃圾收集器開(kāi)始工作,無(wú)論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉只
 * 被弱引用關(guān)聯(lián)的對(duì)象。在JDK 1.2版之后提供了WeakReference類來(lái)實(shí)現(xiàn)弱引用。
 *
 * 應(yīng)用:ThreadLocal
 * @author:weirx
 * @date:2021/5/19 16:54
 * @version:3.0
 */
public class WeakReferenceTest {

    public static void main(String[] args) throws InterruptedException {
        WeakReference<byte[]> w = new WeakReference<>(new byte[1024 * 1024 * 10]);

        System.out.println(w.get());

        System.gc();
        Thread.sleep(1000);

        //只經(jīng)歷一次gc就被回收了
        System.out.println(w.get());

    }
}

結(jié)果:

[B@6f75e721
null

四、虛引用

虛引用也稱為“幽靈引用”或者“幻影引用”,它是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用的存在,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響,也無(wú)法通過(guò)虛引用來(lái)取得一個(gè)對(duì)象實(shí)例。為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的只是為了能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。在JDK 1.2版之后提供了PhantomReference類來(lái)實(shí)現(xiàn)虛引用。

應(yīng)用:在jvm中,用來(lái)管理直接內(nèi)存(例如NIO中ByteBuffer申請(qǐng)直接內(nèi)存allocateDirect)的回收.會(huì)將虛引用的回收時(shí)間添加到一個(gè)隊(duì)列中。通過(guò)檢測(cè)虛引用可以做一些善后操作。

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 虛引用
 * 虛引用也稱為“幽靈引用”或者“幻影引用”,它是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用的
 * 存在,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響,也無(wú)法通過(guò)虛引用來(lái)取得一個(gè)對(duì)象實(shí)例。為一個(gè)對(duì)象設(shè)置虛
 * 引用關(guān)聯(lián)的唯一目的只是為了能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。在JDK 1.2版之后提供
 * 了PhantomReference類來(lái)實(shí)現(xiàn)虛引用
 *
 * 應(yīng)用:在jvm中,用來(lái)管理直接內(nèi)存(例如NIO中ByteBuffer申請(qǐng)直接內(nèi)存allocateDirect)的回收.會(huì)將虛引用的回收時(shí)間添加到一個(gè)隊(duì)列中。
 * @author:weirx
 * @date:2021/5/19 17:09
 * @version:3.0
 */
public class PhantomReferenceTest {

    static class M {
        int a = 0;
    }

    static ReferenceQueue referenceQueue = new ReferenceQueue();

    public static void main(String[] args) {
        PhantomReference phantomReference = new PhantomReference(new M(), referenceQueue);

        //通過(guò)get頁(yè)不能獲取到
        System.out.println(phantomReference.get());

        List list = new ArrayList();
        //模擬線程,不斷增加堆空間占用
        new Thread(() -> {
            while (true) {
                list.add(new byte[1024 * 1024]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        //模擬垃圾回收線程,可用于做善后處理,比如nio的直接內(nèi)存
        new Thread(() -> {
            while (true) {
                //當(dāng)虛引用對(duì)象被回收時(shí),會(huì)在隊(duì)列里面增加一個(gè)信息,當(dāng)我們獲取到信息就可以對(duì)這個(gè)引用做善后處理
                Reference poll = referenceQueue.poll();
                if (poll != null) {
                    System.out.println("虛引用對(duì)象被jvm回收了," + poll);
                }
            }
        }).start();
    }
}

結(jié)果:

null
null
null
null
null
null
null
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
    at com.cloud.bssp.reference.PhantomReferenceTest.lambda$main$0(PhantomReferenceTest.java:44)
    at com.cloud.bssp.reference.PhantomReferenceTest$$Lambda$1/874088044.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
虛引用對(duì)象被jvm回收了,java.lang.ref.PhantomReference@7090cd23
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 強(qiáng)引用: 只要引用存在,垃圾回收器永遠(yuǎn)不會(huì)回收 Object obj = new Object(); //可直接通...
    我這小樣兒閱讀 589評(píng)論 0 2
  • 在JDK1.2之后,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用(Strong Reference),軟引用(...
    是什么樣的心情閱讀 150評(píng)論 0 1
  • Java對(duì)引用的定義 無(wú)論是通用引用計(jì)數(shù)算法判斷對(duì)象的引用數(shù)據(jù),還是通過(guò)可達(dá)性分析算法判斷對(duì)象的引用鏈?zhǔn)欠窨蛇_(dá),判...
    霸體閱讀 371評(píng)論 0 0
  • java的四種引用 強(qiáng)引用是最傳統(tǒng)的“引用”的定義,是指在程序代碼之中普遍存在的引用賦值,即類似“Object o...
    浪夠_閱讀 182評(píng)論 0 0
  • 引語(yǔ): 我們知道java相比C,C++中沒(méi)有令人頭痛的指針,但是卻有和指針作用相似的引用對(duì)象(Reference)...
    編程小世界閱讀 360評(píng)論 0 0

友情鏈接更多精彩內(nèi)容