4種Java引用淺解

來源:互聯網
上載者:User

最近研究Java Cache實現,發現使用到了軟引用(SoftReference),不太理解,查閱了JDK文檔、代碼以及幾篇文章。做個小結,如有錯誤,歡迎指正。

之所以想學習一下Java的幾種參考型別,原因有兩個:

  • 理解Java Cache實現、學習Java引用與Java記憶體回收機制的關係
    記憶體資源是有限的,需要合理的利用。Cache不是僅僅HashMap那麼簡單,Java引用與Java記憶體回收機制也有非常緊密的關係。
  • 避免對Java引用的錯誤使用
    某個同事把5000+交易資料放到一個HashMap裡面,用一個Spring Singleton Bean的全域屬性指向該HashMap。大量運用這種技術,很快就報out of memory。再大的記憶體也架不住對記憶體的錯誤使用。理解原理有助於我們盡量少犯或不犯低級錯誤。
Java引用與Java記憶體回收機制的關係

當Java虛擬機器(JVM)覺得記憶體不夠用的時候,會觸發記憶體回收操作(GC),清除無用的對象,釋放記憶體。可是如何判斷一個對象是否是垃圾呢?其中的一個方法是計算指向該對象的引用數量,如果引用數量為0,那麼該對象就為垃圾(Thread對象是例外),否則還有用處,不能被回收。但是如果把引用數為0的對象都回收了,還是不能滿足記憶體需求怎麼辦?Java把引用分為4種類型,記憶體回收行程會嘗試回收只有弱引用的對象。

按照一個對象的引用可達(Reachable)強度,由強到弱分為5類,如下:

  • 強可達(Strong Reachable)
    在一個線程內,無需引用直接可達,新建立的對象是強可達的。
  • 軟可達(Soft Reachable)
    不是強可達的,但是通過一個軟引用(SoftReference)可達。
  • 弱可達(Soft Reachable)
    既不是強可達也不是軟可達,但是通過一個弱引用(WeakReference)可達。
  • 虛可達(Phantom Reachable)
    既不是強可達,不是軟可達,也不是弱可達,但是通過一個虛引用(PhantomReference)可達。
  • 不可達(Unreachable)
    沒有任何引用指向對象。

比較好、容易理解的是Java記憶體回收行程會優先清理可達強度低的對象。另外有兩個重要的點:

  • 強可達的一定不會被清理
  • JVM保證拋出out of memory之前,清理所有的軟引用對象
4種Java引用

在實現一個緩衝系統的時候,如果全部使用強引用,那麼你需要自己去手動的把某些引用clear掉(引用置位null),否則遲早會拋出out of memory錯誤。緩衝系統引入弱引用或者軟引用的唯一原因是,把引用clear的事情交由Java記憶體回收行程來處理,cache程式自己置身事外

幾種弱引用的使用方式非常相近。下面分別介紹4種參考型別。

強引用(StrongReference)

我們平時申明變數使用的就是強引用,普通系統99%以上都是強引用。比如,String s = "Hello World"

弱引用(WeakReference)

記憶體回收行程某個時刻決定回收軟可達的對象的時候,會清理軟引用,並可選的把引用存放到一個引用隊列(ReferenceQueue)。

軟引用(SoftReference)

類似弱引用,只不過Java虛擬機器會盡量讓軟引用的存活時間長一些,迫不得已才清理。

虛引用(PhantomReference)

僅用來處理資源的清理問題,比Object裡面的finalize機制更靈活。get方法返回的永遠是null,Java虛擬機器不負責清理虛引用,但是它會把虛引用放到引用隊列裡面。

兩個測試例子

使用HashMap,會報out of memory錯誤。

public static void main(String[] args) {Map<String, String> list = new HashMap<String, String>();long i = 1;while (i < 100000000L) {list.put(String.valueOf(i),"JDJJDJJJJJJJJJJ%%%%%%%%JJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKJJJJJJ"+ "JJJKKKKKHDDDJDJDJDJDJDJDJDJJDJDJDJDJDJDJJDJDJDJDJJDJDJJJJJJJJJ"+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJ");// 測試第一個是否依然存活if (i % 100000 == 0) {System.out.println(list.get(String.valueOf(1)));}i++;}}

使用WeakHashMap,不會報out of memory錯誤。

public static void main(String[] args) {Map<String, String> list = new WeakHashMap<String, String>();long i = 1;while (i < 100000000L) {list.put(String.valueOf(i),"JDJJDJJJJJJJJJJ%%%%%%%%JJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKJJJJJJ"+ "JJJKKKKKHDDDJDJDJDJDJDJDJDJJDJDJDJDJDJDJJDJDJDJDJJDJDJJJJJJJJJ"+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"+ "JJJJJJJJJJJJJJJJJJJJJJJJJJJJ");// 測試第一個是否依然存活if (i % 100000 == 0) {System.out.println(list.get(String.valueOf(1)));}i++;}}


小結

Java語言裡面數組(Array)、列表(List)、Map等容器,對裡面的每一個對象都有一個引用,大資料的情況下要小心記憶體泄露。弱引用只適合cache等特殊情境,對於那些一定不能Java讓記憶體回收行程回收的對象,要使用強引用。

參考串連
  • 理解弱引用
  • JDK java.lang.ref包文檔,以及類說明

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.