Java語言中的四種引用區(qū)別

本篇內容介紹了“Java語言中的四種引用區(qū)別”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

成都創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站制作、網(wǎng)站建設與策劃設計,西湖網(wǎng)站建設哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設10多年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:西湖等地區(qū)。西湖做網(wǎng)站價格咨詢:18982081108

四種引用的區(qū)別

其實四種引用的區(qū)別在于GC的時候,對它們的處理不同。用一句話來概括,就是:如果一個對象GC Root可達,強引用不會被回收,軟引用在內存不足時會被回收,弱引用在這個對象第一次GC會被回收。

如果GC Root不可達,那不論什么引用,都會被回收

虛引用比較特殊,等于沒有引用,不會影響對象的生命周期,但可以在對象被收集器回收時收到一個系統(tǒng)通知。

下面結合案例分別來講一下四種引用在面對GC時的表現(xiàn)以及它們的常見用途。先設置一下JVM的參數(shù):

-Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails

強引用

這就是我們平時最常使用的引用。只要GC的時候這個對象GC Root可達,它就不會被回收。如果JVM內存不夠了,直接拋出OOM。比如下面這段代碼就會拋出OutOfMemoryError:

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

軟引用

軟引用,當GC的時候,如果GC Root可達,如果內存足夠,就不會被回收;如果內存不夠用,會被回收。將上面的例子改成軟引用,就不會被OOM:

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

我們把程序改造一下,打印出GC后的前后的差別:

public static void main(String[] args) {
   List<SoftReference<byte[]>> list = new LinkedList<>();
   for (int i = 0; i < 21; i++) {
       SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024]);
       list.add(softReference);
       System.out.println("gc前:" + softReference.get());
   }
   System.gc();
   for (SoftReference<byte[]> softReference : list) {
       System.out.println("gc后:" + softReference.get());
   }
}

會發(fā)現(xiàn),打印出的日志,GC前都是有值的,而GC后,會有一些是null,代表它們已經(jīng)被回收。

而我們設置的堆最大為20M,如果把循環(huán)次數(shù)改成15,就會發(fā)現(xiàn)打印出的日志,GC后沒有為null的。但通過-verbose:gc -XX:+PrintGCDetails參數(shù)能發(fā)現(xiàn),JVM還是進行了幾次GC的,只是由于內存還夠用,所以沒有回收。

public static void main(String[] args) {
   List<SoftReference<byte[]>> list = new LinkedList<>();
   for (int i = 0; i < 15; i++) {
       SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024]);
       list.add(softReference);
       System.out.println("gc前:" + softReference.get());
   }
   System.gc();
   for (SoftReference<byte[]> softReference : list) {
       System.out.println("gc后:" + softReference.get());
   }
}

所以軟引用的常見用途就呼之欲出了:緩存。尤其是那種希望這個緩存能夠持續(xù)時間長一點的。

弱引用

軟引用,只要這個對象發(fā)生GC,就會被回收。

把上面的代碼改成軟引用,會發(fā)現(xiàn)打印出的日志,GC后全部為null。

public static void main(String[] args) {
   List<WeakReference<byte[]>> list = new LinkedList<>();
   for (int i = 0; i < 15; i++) {
       WeakReference<byte[]> weakReference = new WeakReference<>(new byte[1024 * 1024]);
       list.add(weakReference);
       System.out.println("gc前:" + weakReference.get());
   }
   System.gc();
   for (WeakReference<byte[]> weakReference : list) {
       System.out.println("gc后:" + weakReference.get());
   }
}

所以弱引用也適合用來做緩存,不過由于它是只要發(fā)生GC就會被回收,所以存活的時間比軟引用短得多,通常用于做一些非常臨時的緩存。

我們知道,WeakHashMap內部是通過弱引用來管理entry的。它的鍵是“弱鍵”,所以在GC時,它對應的鍵值對也會從Map中刪除。

Tomcat中有一個ConcurrentCache,用到了WeakHashMap,結合ConcurrentHashMap,實現(xiàn)了一個線程安全的緩存,感興趣的同學可以研究一下源碼,代碼非常精簡,加上所有注釋,只有短短59行。

ThreadLocal中的靜態(tài)內部類ThreadLocalMap里面的entry是一個WeakReference的繼承類。

使用弱引用,使得ThreadLocalMap知道ThreadLocal對象是否已經(jīng)失效,一旦該對象失效,也就是成為垃圾,那么它所操控的Map里的數(shù)據(jù)也就沒有用處了,因為外界再也無法訪問,進而決定擦除Map中相關的值對象,Entry對象的引用,來保證Map總是保持盡可能的小。

虛引用

虛引用的設計和上面三種引用有些不同,它并不影響GC,而是為了在對象被GC時,能夠收到一個系統(tǒng)通知。

那它是怎么被通知的呢?虛引用必須要配合ReferenceQueue,當GC準備回收一個對象,如果發(fā)現(xiàn)它還有虛引用,就會在回收之前,把這個虛引用加入到與之關聯(lián)的ReferenceQueue中。

那NIO是如何利用虛引用來管理內存的呢?

DirectBuffer直接從Java堆之外申請一塊內存, 這塊內存是不直接受JVM GC管理的, 也就是說在GC算法中并不會直接操作這塊內存. 這塊內存的GC是由于DirectBuffer在Java堆中的對象被GC后, 通過一個通知機制, 而將其清理掉的.

DirectBuffer內部有一個Cleaner。這個Cleaner是PhantomReference的子類。當DirectBuffer對象被回收之后, 就會通知到PhantomReference。然后由ReferenceHandler調用tryHandlePending()方法進行pending處理. 如果pending不為空, 說明DirectBuffer被回收了, 就可以調用Cleaner的clean()進行回收了。

上面這個方法的代碼在Reference類里面,有興趣的同學可以去看一下那個方法的源碼。

總結

以上就是Java中四種引用的區(qū)別。一般來說,強引用我們都知道,虛引用很少用到。而軟引用和弱引用的區(qū)別在于回收的時機:軟引用GC時,發(fā)現(xiàn)內存不夠才回收,弱引用只要一GC就會回收。

“Java語言中的四種引用區(qū)別”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質量的實用文章!

分享題目:Java語言中的四種引用區(qū)別
當前鏈接:http://muchs.cn/article44/ipgshe.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、微信公眾號、小程序開發(fā)、手機網(wǎng)站建設、用戶體驗靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設