Java の 四種引用

来源:https://www.cnblogs.com/lawsssscat/archive/2020/04/13/12689065.html
-Advertisement-
Play Games

Java 中所謂的引用,看似是指針的問題,實則體現的是JVM對記憶體的管理思想。 -- 魯迅 ...


介紹

在JAVA中提供了四種引用類型:強引用、軟引用、軟引用和虛引用。

在四種引用類型中,只有強引用FinalReference類型變數是包內可見的,其他三種引用類型均為public,可以在程式中直接使用

強引用

強引用是使用最普遍的引用。如果一個對象具有強引用,那麼垃圾回收器絕不會回收它

例如:

StringBuilder sb = new StringBuilder("test");

變數str指向StringBuffer實例所在的堆空間,通過str可以操作該對象。
如下:

  • 強引用可以直接訪問目標對象
  • 只要有引用變數存在,垃圾回收器永遠不會回收。JVM即使拋出OOM異常,也不會回收強引用所指向的對象。
  • 強引用可能導致記憶體泄漏問

軟引用

軟引用是除了強引用外,最強的引用類型。一個持有軟引用的對象,只有在記憶體不足時,gc才會回收它

可以通過java.lang.ref.SoftReference使用軟引用

SoftReference 的特點是:
一旦SoftReference保存了一個Java對象的軟引用後

  • 在垃圾線程對這個Java對象回收前,SoftReference類所提供的get()方法返回Java對象的強引用。
  • 一旦垃圾線程回收該Java對象之後,get()方法將返回null。

如下:

Object obj = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
SoftReference<Object> sf = new SoftReference<Object>(obj, queue); // 只能這麼創建
obj = null;
System.out.println("引用值:" + sf.get());
System.out.println("被標記:" + sf.isEnqueued());
System.out.println("被回收:" + queue.poll());
System.gc();
System.out.println("引用值:" + sf.get() + "(gc後)"); // 有gc,不一定為null。記憶體不足時,為null
System.out.println("被標記:" + sf.isEnqueued() + "(gc後)");
System.out.println("被回收:" + queue.poll() + "(gc後)");

  • sf是對obj的一個軟引用,通過sf.get()方法可以取到 這個對象
  • 這個對象 被標記為需要回收的對象時,則返回null
    (上面例子不為null,說明對象未被gc標記為垃圾)

一個持有軟引用的對象,不會被JVM很快回收,JVM會根據當前堆的使用情況來判斷何時回收。當堆使用率臨近閾值時,才會去回收軟引用的對象。

  1. 因此,軟引用可以用於實現對記憶體敏感的高速緩存

    • 在記憶體足夠的情況下直接通過軟引用取值,無需從繁忙的真實來源查詢數據,提升速度;
    • 當記憶體不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。
  2. 使用軟引用能防止記憶體泄露,增強程式的健壯性

    記憶體泄漏:既存在一部分記憶體一直處於空閑狀態。

  3. 軟引用可以和一個引用隊列(ReferenceQueue)聯合使用
    ReferenceQueue中保存已經失去了它所軟引用的對象的Reference對象。
    (參考“弱引用”)

    利用ReferenceQueue的poll()方法,可以檢查哪個SoftReference所軟引用的對象已經被回收,於是可以把這些失去所軟引用的對象的SoftReference對象清除掉。

弱引用

弱引用是一種比軟引用較弱的引用類型。一個被弱引用的對象,不管系統堆空間是否足夠,gc都會將對象進行回收。

在java中,可以用java.lang.ref.WeakReference實例來保存對一個Java對象的弱引用。

Object obj = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> sf = new WeakReference<Object>(obj, queue); // 只能這麼創建
obj = null;
System.out.println("引用值:" + sf.get());
System.out.println("被標記:" + sf.isEnqueued());
System.out.println("被回收:" + queue.poll());
System.gc();
System.out.println("引用值:" + sf.get() + "(gc後)"); // 只要有gc,就為null
System.out.println("被標記:" + sf.isEnqueued() + "(gc後)");
System.out.println("被回收:" + queue.poll() + "(gc後)");

弱引用的應用:WeakHashMap

Object key = new Object();
// WeakHashMap 的弱引用對象是key,而value是強引用存儲在WeakHashMap內部
WeakHashMap<Object, Object> map = new WeakHashMap<>();
map.put(key, "haha");
System.out.println("obj:" + map.get(key));
System.out.println("size:" + map.size());
System.gc();
System.out.println("obj:" + map.get(key) + "(gc後)");
System.out.println("size:" + map.size());
// 清除強引用
key = null;
// 調用gc清除弱引用
System.gc();
System.out.println("obj:" + map.get(key) + "(gc後,obj=null後)");
System.out.println("size:" + map.size());

20200413105419

最後提醒一句:WeakHashMap 不是線程安全的,要在併發場景下使用,記得使用 Collections.synchronizedMap 包一層

虛引用

虛引用是所有類型中最弱的一個。一個持有虛引用的對象和沒有引用幾乎是一樣的,隨時可能被垃圾回收器回收。當試圖通過虛引用的get()方法取得強引用時,總是會失敗。

phantom 幽靈

Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue<>();
PhantomReference sf = new PhantomReference(obj, queue); // 只能這麼創建
obj = null;
System.out.println("引用值:" + sf.get());
System.out.println("被標記:" + sf.isEnqueued());
System.out.println("被回收:" + queue.poll());
System.gc();
System.out.println("引用值:" + sf.get() + "(gc後)");
System.out.println("被標記:" + sf.isEnqueued() + "(gc後)");
System.out.println("被回收:" + queue.poll() + "(gc後)");

虛引用必須和引用隊列一起使用,它的作用在於檢測對象是否已經從記憶體中刪除,跟蹤垃圾回收過程

當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在垃圾回收後,銷毀這個對象,將這個虛引用加入引用隊列。程式可以通過判斷引用隊列中是否已經加入了虛引用,來瞭解被引用的對象是否將要被垃圾回收


參考:


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

-Advertisement-
Play Games
更多相關文章
  • react fiber 指react 16以上的版本 引入react的方式: 1、引入.js文件 2、使用腳手架工具(推薦) 推薦使用react官方提供的腳手架工具:create-react-app React開發環境準備 (npx 是 npm 的高級版本,npx 具有更強大的功能) npx cre ...
  • JavaScript 中 apply、call、bind方法的異同: 相同點 都是用來動態指定函數 this 對象的指向 第一個參數都是 this 要指向的對象,也就是要指定的上下文 都可以利用後續參數傳參 不同點 傳參形式不同:apply 方法接受的是一個參數數組,call 和 bind 方法接受 ...
  • TypeScript聯合類型 聯合類型表示取值可以為多種類型中的一種 如下所示 這一塊我們必須使用string或者number都支持的類型,那麼下麵我們可以進行調用擴展方法toString() TypeScript中對象類型 介面 介面可以描述一種抽象的行為,也可以描述對象的結構形狀,當然我們也需要 ...
  • v-bind:class=" " 綁定樣式 <div id="app"> <!-- 值是對象形式,欄位名是class樣式名,值是boolean值,true是引用該樣式,false不引用 --> <!-- 值是false,只是不引用該樣式,並不是就不顯示該元素了 --> <p v-bind:class ...
  • 前臺:支持(5+3[時尚單頁風格])八套模版,可以在後臺切換 業務模塊(首頁管理) 1. 網站信息:維護網站基本信息,比如標題、描述、關鍵詞、聯繫方式、地址等 2. 業務說明:網站首頁文字業務介紹 3. 公司理念:網站首頁展示公司的4個理念 4. 輪播圖片:網站首頁上面4個輪播圖5. 項目案例:網站 ...
  • 在前面的博客中已經介紹過如何使用Python來操作MySQL資料庫,最近需要將一批數據從csv文件中遷移到Oracle資料庫中,也打算用Python來實現,趁著這個機會,也寫一篇博客學習總結一些如何使用Python來操作Oracle資料庫。 ...
  • 原文鏈接:http://www.yiidian.com/fastjson/fastjson json javabean.html 1 簡單JSON與JavaBean的轉換 1.1 設計Student實體類 1.2 簡單JSON轉為JavaBean MainApp: 運行效果為: 1.3 JavaBe ...
  • 虛擬機 虛擬機簡介 Java 虛擬機(JVM)是運行java程式的抽象電腦,它是電腦設備的規範,可以採用不同方式進行實現,java 程式通過運行在JVM中實現跨平臺,一次編譯到處運行,不同的操作系統有不同的JDK版本,通過調用JNI方法去實現調用不同操作系統的方法 Java虛擬機不和包括java ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...