Java 四種引用類型(強引用、軟引用、弱引用、虛引用)

来源:https://www.cnblogs.com/Yee-Q/archive/2023/11/15/17833933.html
-Advertisement-
Play Games

概述 Java 中的引用類似 C 語言中的指針,指向一個對象,比如: // person 就是指向 Person 實例“張三”的引用 Person person = new Person("張三"); 在 JDK1.2 以前,Java 里的引用是很傳統的定義:如果 reference 類型的數據中存 ...


概述

Java 中的引用類似 C 語言中的指針,指向一個對象,比如:

// person 就是指向 Person 實例“張三”的引用
Person person = new Person("張三");

在 JDK1.2 以前,Java 里的引用是很傳統的定義:如果 reference 類型的數據中存儲的數值代表的是另外一塊記憶體的起始地址,就稱該 reference 數據是代表某塊記憶體、某個對象的引用

這種定義當然沒有什麼不對,但現在看來顯得太狹隘了,比如我們希望描述一類對象:當記憶體空間足夠時,能保留在記憶體中,如果記憶體空間在進行了垃圾收集後仍然緊張,則可以拋棄這些對象,很多系統的緩存功能都符合這樣的應用場景

JDK1.2 對引用的概念作了補充,將引用分為強引用(Strongly Reference)、軟引用(SoftReference)、弱引用(Weak Reference)和虛引用(Phantom Reference),強度依次減弱


強引用

Java 中最常見的就是強引用,把一個對象賦給一個引用變數,這個引用變數就是一個強引用。類似 Object obj = new Object()

當一個對象被強引用變數引用時,除非超過了引用的作用域或者顯示地將相應強引用賦值為 null,否則是不可能被垃圾回收器回收的


軟引用

軟引用用來描述一些有用但非必須的對象,此類對象只有在進行一次垃圾收集仍然沒有足夠記憶體時,才會在第二次垃圾收集時被回收,需要用 java.lang.ref.SoftReference 類來實現

public class SoftRefenenceDemo {

    public static void main(String[] args) {
        softRefMemoryEnough();
        System.out.println("------------");
        softRefMemoryNotEnough();
    }

    private static void softRefMemoryEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);  // java.lang.Object@2503dbd3
        System.out.println(s1.get());  // java.lang.Object@2503dbd3

        o1 = null;
        System.gc();

        System.out.println(o1);  // null
        System.out.println(s1.get());  // java.lang.Object@2503dbd3
    }

     /**
      * JVM配置 -Xms5m -Xmx5m ,故意 new 一個大對象,使記憶體不足產生 OOM,看軟引用回收情況
      */
    private static void softRefMemoryNotEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);  // java.lang.Object@4b67cf4d
        System.out.println(s1.get());  // java.lang.Object@4b67cf4d

        o1 = null;
        
        try {
          byte[] bytes = new byte[10 * 1024 * 1024];
        } catch(Error e) {
          e.printStackTrace();
        }
        

        System.out.println(o1);  // null
        System.out.println(s1.get());  // null
    }
}

弱引用

弱引用用來描述那些非必須對象,但它的強度比軟引用更弱一些。被軟引用關聯的對象只能生存到下一次垃圾收集發生為止,當垃圾收集器開始工作,無論當前記憶體是否足夠,都會回收掉只被弱引用關聯的對象,需要用 java.lang.ref.WeakReference 類來實現

public class WeakReferenceDemo {

    public static void main(String[] args) {
        Object o1 = new Object();
        WeakReference<Object> w1 = new WeakReference<Object>(o1);

        System.out.println(o1);  // java.lang.Object@7440e464
        System.out.println(w1.get());  // java.lang.ref.WeakReference@49476842

        o1 = null;
        System.gc();

        System.out.println(o1);  // null
        System.out.println(w1.get());  // null
    }
}

虛引用

虛引用,顧名思義,就是形同虛設,與其他幾種引用都不太一樣,一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。虛引用必須和引用隊列(RefenenceQueue)聯合使用。虛引用的主要作用是跟蹤對象垃圾回收的狀態,僅僅是提供了一種確保對象被 finalize 以後,收到一個系統通知或者後續添加進一步的處理

public class PhantomReferenceDemo {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
        PhantomReference<Object> phantomReference = new PhantomReference<Object>(o1,referenceQueue);

        System.out.println(o1);  // java.lang.Object@7440e464
        System.out.println(referenceQueue.poll());  // null
        System.out.println(phantomReference.get());  // null

        o1 = null;
        System.gc();
        Thread.sleep(3000);

        System.out.println(o1);  // null
        System.out.println(referenceQueue.poll()); // java.lang.ref.PhantomReference@49476842
        System.out.println(phantomReference.get());  // null
    }

}

ReferenceQueue 是用來配合引用工作的,沒有ReferenceQueue 一樣可以運行。SoftReference、WeakReference、PhantomReference 都有一個可以傳遞 ReferenceQueue 的構造器。創建引用的時候,可以指定關聯的隊列,當 GC 釋放對象記憶體的時候,會將引用加入到引用隊列。如果程式發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的記憶體被回收之前採取必要的行動,這相當於是一種通知機制。當關聯的引用隊列中有數據的時候,意味著指向的堆記憶體中的對象被回收。通過這種方式,JVM 允許我們在對象被銷毀後,做一些我們自己想做的事情


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、提示 由於國內註冊 https://api.openai.com 比較麻煩,直接購買的第三方介面和key 淘寶購買,幾塊錢1個月 3、自己娛樂夠用 2、前端框架 Vant 移動端使用 axios 3、創建攔截器,api/request.js /* * @Descripttion: 文件說明 * ...
  • 跨域這兩個字就像一塊狗皮膏藥一樣黏在每一個前端開發者身上,無論你在工作上或者面試中無可避免會遇到這個問題。如果在網上搜索跨域問題,會出現許許多多方案,這些方案有好有壞,但是對於闡述跨域的原理和在什麼情況下需要用什麼方案,缺少系統性的說明。大家在工作中可能因為大佬們已經配置好了,不會產生跨域,但是作為... ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:奇銘 前言 目前數棧的多個產品中都支持線上編輯 SQL 來生成對應的任務。比如離線開發產品和實時開發產品。在使用 MonacoEditor 為編輯器的基礎上, ...
  • 需求落地分散式應用服務 將需求轉化為分散式應用服務的過程可以按照以下步驟進行: 理解需求:首先,你需要仔細閱讀和理解業務需求。與相關的利益相關者(如業務分析師、產品經理等)進行溝通,確保你對需求的理解是準確的。 設計架構:根據需求,設計一個適合的分散式應用架構。這包括確定應用的組件和模塊,以及它們之 ...
  • 本文介紹了結構型設計模式中的代理設計模式,講解了靜態代理、JDK的動態代理和cglib的動態代理,並用代碼進行演示。 ...
  • 故事很老套。。就一堆漂亮姑娘毫無道理的、莫名其妙的往死里貼“我”,很煩人~只要略施小計,就能將她們攬入懷中,非常魔幻。 因為這游戲不只是火,同時還口碑超高。《美女包圍》剛發售時的好評率是83%,火了後評價不降反升,現在是恐怖的93%。 性感辣媽林樂清 —— 王星辰(身材姣好,入得廳堂下得廚房,娶妻當 ...
  • 定義 最短路樹:以圖上一個點為根節點,刪去部分邊後所形成的樹,樹的邊權滿足任意一點與根結點的路徑長度等於圖上兩點的最短路徑長度。 求法 可以採用 dij 求解。 每次更新 \(dis_v\) 時,記錄每個點最後一次用來更新的邊,即為最短路樹。 核心代碼如下,時間複雜度為 dij 的時間複雜度即 \( ...
  • 來源:juejin.cn/post/7023317351563001886 1、概述 SpringBoot框架不用多介紹,Java程式員想必都知道。相對來說熟悉Quarkus的人可能會少一些。Quarkus首頁放出的標語:超音速亞原子的Java(Supersonic Subatomic Java)。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...