Java中的 WeakReference 和 SoftReference

來源:互聯網
上載者:User

標籤:

我們知道Java語言中沒有指標,取而代之的是引用reference。Java中的引用又可以分為四種:強引用,弱引用(WeakReference),軟引用(SoftReference),虛引用(PhantomReference)。其中強引用,就是我們平時使用的最多的最普通的引用,虛引用一般我們是沒有機會使用到的。所以我們主要瞭解下 WeakReference 和 SoftReference

1. 先上一段代碼:

public class ReferenceTest {    public static void main(String[] args){        LinkedList<byte[]> list = new LinkedList<>();        for(int i=0; i<1024; i++){            list.add(new byte[1024*1024]);        }    }}

上面的代碼會拋出:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

堆記憶體溢出。因為我們不斷的在堆上分配一個 1M 大小的 byte[]對象,並且將該引用加入到 list 中,迴圈1024次,需要佔用 1G 的堆記憶體,從而導致 heap space OutOfMemory.

2. 我們使用 WeekReference 對代碼進行修改:

public class ReferenceTest {    public static void main(String[] args) {        long beginTime = System.nanoTime();        LinkedList<WeakReference<byte[]>> list = new LinkedList<>();        for (int i = 0; i < 1024; i++) {            list.add(new WeakReference<>(new byte[1024 * 1024]));        }        long endTime = System.nanoTime();        System.out.println(endTime - beginTime);    }}

輸出的結果:195947704 (0.19秒)

我們發現堆記憶體溢出的錯誤沒有了。這是什麼原因呢。因為我們使用了 弱引用WeekReference 來引用堆上的 1M 的byte[]對象,而弱引用WeekReference引用的對象,如果僅僅只被弱引用,而沒有被強引用的話,在下一次GC時,就會回收該對象佔用的記憶體,所以不會記憶體溢出。

3. 我們使用 SoftReference 對代碼進行修改:

public class ReferenceTest {    public static void main(String[] args) {        long beginTime = System.nanoTime();        LinkedList<SoftReference<byte[]>> list = new LinkedList<>();        for (int i = 0; i < 1024; i++) {            list.add(new SoftReference<>(new byte[1024 * 1024]));        }        long endTime = System.nanoTime();        System.out.println(endTime - beginTime);    }}

輸出結果:1499904286 (1.5秒)

我們發現堆記憶體溢出的錯誤也沒有了。因為我們使用了 軟引用SoftReference 來引用堆上的 1M 的byte[]對象,而軟引用SoftReference引用的對象,如果僅僅只被軟引用,而沒有被強引用的話,在記憶體空間不足時,GC 就會回收該對象佔用的記憶體,所以不會記憶體溢出。

但是我們注意到 採用WeekReference和採用SoftReference所花費的時間,有接近10被的差距。原因應該是,SoftReference只有在記憶體空間不足時,GC才會回收對象佔用的空間,而這時進行的是 full GC,full GC會導致 STW 程式暫停,所以花費的時間過多。

4. 總結

強引用:只要堆上的對象,被至少一個強引用所指向,那麼GC就不會回收該對象的記憶體空間。

弱引用:只要堆上的對象僅僅只被弱引用所指向,不管當前記憶體空間是否足夠,下次GC都會回收對象的記憶體空間。

軟引用:只要堆上的對象僅僅只被軟引用所指向,並且當記憶體空間不足時,GC才會回收對象的記憶體空間。

WeakReference 和 SoftReference一般使用在構造一個緩衝系統,比如使用一個map來構造。因為緩衝系統是一個“全生命期”的對象,系統停止,緩衝對象才會被銷毀,所以當我們不斷的想緩衝對象中添加對象時,那麼就會導致該緩衝對象map所引用的對象越來越多,而因為是強引用,這些被放進map緩衝了的對象不能被GC鎖回收,那麼就導致系統堆記憶體佔用會越來越大,從而最終導致記憶體溢出。

那麼此時我們就可以使用 WeakReference 或 SoftReference了,將強引用通過WeakReference 和 SoftReference 封裝之後,變成弱引用和軟引用,那麼當緩衝中的對象,僅僅被緩衝map鎖引用時,那麼分別在下次GC和記憶體不足GC時就會回收這些對象佔用的記憶體。其實JDK給我們提供了一個專門的類:WeakHashMap ,弱引用的hashMap,所以構造緩衝系統是,我們可以考慮使用它。

其實這裡涉及到jdk中眾多的map,我們應該如何進行選擇的問題:

HashMap

ConcurrentHashMap

TreeMap

WeakHashMap

LinkedHashMap

Collections.synchronizedMap

Hashtable

等等。我們在選擇一個map時,應該好好的考慮下,那個更加適合我們的需求。

 

Java中的 WeakReference 和 SoftReference

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.