国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Java語(yǔ)言中的四種引用區別

發(fā)布時(shí)間:2021-09-14 11:25 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 網(wǎng)絡(luò )安全 歡迎投稿:712375056

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

四種引用的區別

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

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

虛引用比較特殊,等于沒(méi)有引用,不會(huì )影響對象的生命周期,但可以在對象被收集器回收時(shí)收到一個(gè)系統通知。

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

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

強引用

這就是我們平時(shí)最常使用的引用。只要GC的時(shí)候這個(gè)對象GC Root可達,它就不會(huì )被回收。如果JVM內存不夠了,直接拋出OOM。比如下面這段代碼就會(huì )拋出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的時(shí)候,如果GC Root可達,如果內存足夠,就不會(huì )被回收;如果內存不夠用,會(huì )被回收。將上面的例子改成軟引用,就不會(huì )被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());
   }
}

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

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

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());
   }
}

所以軟引用的常見(jiàn)用途就呼之欲出了:緩存。尤其是那種希望這個(gè)緩存能夠持續時(shí)間長(cháng)一點(diǎn)的。

弱引用

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

把上面的代碼改成軟引用,會(huì )發(fā)現打印出的日志,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());
   }
}

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

我們知道,WeakHashMap內部是通過(guò)弱引用來(lái)管理entry的。它的鍵是“弱鍵”,所以在GC時(shí),它對應的鍵值對也會(huì )從Map中刪除。

Tomcat中有一個(gè)ConcurrentCache,用到了WeakHashMap,結合ConcurrentHashMap,實(shí)現了一個(gè)線(xiàn)程安全的緩存,感興趣的同學(xué)可以研究一下源碼,代碼非常精簡(jiǎn),加上所有注釋?zhuān)挥卸潭?9行。

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

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

虛引用

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

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

那NIO是如何利用虛引用來(lái)管理內存的呢?

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

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

上面這個(gè)方法的代碼在Reference類(lèi)里面,有興趣的同學(xué)可以去看一下那個(gè)方法的源碼。

總結

以上就是Java中四種引用的區別。一般來(lái)說(shuō),強引用我們都知道,虛引用很少用到。而軟引用和弱引用的區別在于回收的時(shí)機:軟引用GC時(shí),發(fā)現內存不夠才回收,弱引用只要一GC就會(huì )回收。

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

超碰日本爆乳中文字幕| 成年大片视频免费视频无广告| 成人免费韩漫网站无遮羞| A级毛片100部免费观看 | 在线观看成人无码中文AV天堂| 西西人体444RT高清大胆图片|