成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡(jiǎn)單理解Java GC與幽靈引用

開(kāi)發(fā) 后端
Java中一共有4種類型的引用:StrongReference、SoftReference、WeakReference以及PhantomReference (幽靈引用), 這 4 種類型的引用與Java GC有著密切的關(guān)系, 讓我們逐一來(lái)看它們的定義和使用場(chǎng)景。

1. Strong Reference

StrongReference 是 Java 的默認(rèn)引用實(shí)現(xiàn),它會(huì)盡可能長(zhǎng)時(shí)間的存活于 JVM 內(nèi), 當(dāng)沒(méi)有任何對(duì)象指向它時(shí)Java GC 執(zhí)行后將會(huì)被回收

  1. @Test  
  2. public void strongReference() {   
  3. Object referent = new Object();   
  4.    
  5. /**  
  6.  * 通過(guò)賦值創(chuàng)建 StrongReference   
  7.  */  
  8. Object strongReference = referent;   
  9.    
  10. assertSame(referent, strongReference);   
  11.    
  12. referent = null;   
  13. System.gc();   
  14.    
  15. /**  
  16.  * StrongReference 在 GC 后不會(huì)被回收  
  17.  */  
  18. assertNotNull(strongReference);   
  19. }   
  20.  
  21.  @Test  
  22.  public void strongReference() {  
  23.   Object referent = new Object();  
  24.     
  25.   /**  
  26.    * 通過(guò)賦值創(chuàng)建 StrongReference   
  27.    */  
  28.   Object strongReference = referent;  
  29.     
  30.   assertSame(referent, strongReference);  
  31.     
  32.   referent = null;  
  33.   System.gc();  
  34.     
  35.   /**  
  36.    * StrongReference 在 GC 后不會(huì)被回收  
  37.    */  
  38.   assertNotNull(strongReference);  
  39.  } 

2. WeakReference & WeakHashMap

WeakReference, 顧名思義,是一個(gè)弱引用,當(dāng)所引用的對(duì)象在 JVM 內(nèi)不再有強(qiáng)引用時(shí), Java GC 后 weak reference 將會(huì)被自動(dòng)回收

  1. @Test  
  2. public void weakReference() {   
  3. Object referent = new Object();   
  4. WeakReference<Object> weakRerference = new WeakReference<Object>(referent);   
  5.  
  6. assertSame(referent, weakRerference.get());   
  7.    
  8. referent = null;   
  9. System.gc();   
  10.    
  11. /**  
  12.  * 一旦沒(méi)有指向 referent 的強(qiáng)引用, weak reference 在 GC 后會(huì)被自動(dòng)回收  
  13.  */  
  14. assertNull(weakRerference.get());   
  15. }   
  16.  
  17.  @Test  
  18.  public void weakReference() {  
  19.   Object referent = new Object();  
  20.   WeakReference<Object> weakRerference = new WeakReference<Object>(referent);  
  21.    
  22.   assertSame(referent, weakRerference.get());  
  23.     
  24.   referent = null;  
  25.   System.gc();  
  26.     
  27.   /**  
  28.    * 一旦沒(méi)有指向 referent 的強(qiáng)引用, weak reference 在 GC 后會(huì)被自動(dòng)回收  
  29.    */  
  30.   assertNull(weakRerference.get());  
  31.  } 

WeakHashMap 使用 WeakReference 作為 key, 一旦沒(méi)有指向 key 的強(qiáng)引用, WeakHashMap 在Java GC 后將自動(dòng)刪除相關(guān)的 entry

  1. @Test  
  2. public void weakHashMap() throws InterruptedException {   
  3. Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();   
  4. Object key = new Object();   
  5. Object value = new Object();   
  6. weakHashMap.put(key, value);   
  7.  
  8. assertTrue(weakHashMap.containsValue(value));   
  9.    
  10. key = null;   
  11. System.gc();   
  12.    
  13. /**  
  14.  * 等待無(wú)效 entries 進(jìn)入 ReferenceQueue 以便下一次調(diào)用 getTable 時(shí)被清理  
  15.  */  
  16. Thread.sleep(1000);   
  17.    
  18. /**  
  19.  * 一旦沒(méi)有指向 key 的強(qiáng)引用, WeakHashMap 在 GC 后將自動(dòng)刪除相關(guān)的 entry  
  20.  */  
  21. assertFalse(weakHashMap.containsValue(value));   
  22. }   
  23.  
  24.  @Test  
  25.  public void weakHashMap() throws InterruptedException {  
  26.   Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();  
  27.   Object key = new Object();  
  28.   Object value = new Object();  
  29.   weakHashMap.put(key, value);  
  30.    
  31.   assertTrue(weakHashMap.containsValue(value));  
  32.     
  33.   key = null;  
  34.   System.gc();  
  35.     
  36.   /**  
  37.    * 等待無(wú)效 entries 進(jìn)入 ReferenceQueue 以便下一次調(diào)用 getTable 時(shí)被清理  
  38.    */  
  39.   Thread.sleep(1000);  
  40.     
  41.   /**  
  42.    * 一旦沒(méi)有指向 key 的強(qiáng)引用, WeakHashMap 在 GC 后將自動(dòng)刪除相關(guān)的 entry  
  43.    */  
  44.   assertFalse(weakHashMap.containsValue(value));  
  45.  } 

 3. SoftReference

SoftReference 于 WeakReference 的特性基本一致, ***的區(qū)別在于 SoftReference 會(huì)盡可能長(zhǎng)的保留引用直到 JVM 內(nèi)存不足時(shí)才會(huì)被回收(虛擬機(jī)保證), 這一特性使得 SoftReference 非常適合緩存應(yīng)用

  1. @Test  
  2. public void softReference() {   
  3. Object referent = new Object();   
  4. SoftReference<Object> softRerference = new SoftReference<Object>(referent);   
  5.  
  6. assertNotNull(softRerference.get());   
  7.    
  8. referent = null;   
  9. System.gc();   
  10.    
  11. /**  
  12.  *soft references 只有在 jvm OutOfMemory 之前才會(huì)被回收, 所以它非常適合緩存應(yīng)用  
  13.  */  
  14. assertNotNull(softRerference.get());   
  15. }   
  16.  
  17.  @Test  
  18.  public void softReference() {  
  19.   Object referent = new Object();  
  20.   SoftReference<Object> softRerference = new SoftReference<Object>(referent);  
  21.    
  22.   assertNotNull(softRerference.get());  
  23.     
  24.   referent = null;  
  25.   System.gc();  
  26.     
  27.   /**  
  28.    *soft references 只有在 jvm OutOfMemory 之前才會(huì)被回收, 所以它非常適合緩存應(yīng)用  
  29.    */  
  30.   assertNotNull(softRerference.get());  
  31.  } 

4. PhantomReference

作為本文主角, Phantom Reference(幽靈引用) 與 WeakReference 和 SoftReference 有很大的不同,因?yàn)樗?get() 方法永遠(yuǎn)返回 null, 這也正是它名字的由來(lái)

  1. @Test  
  2. public void phantomReferenceAlwaysNull() {   
  3. Object referent = new Object();   
  4. PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());   
  5.    
  6. /**  
  7.  * phantom reference 的 get 方法永遠(yuǎn)返回 null   
  8.  */  
  9. assertNull(phantomReference.get());   
  10. }   
  11.  
  12.  @Test  
  13.  public void phantomReferenceAlwaysNull() {  
  14.   Object referent = new Object();  
  15.   PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());  
  16.     
  17.   /**  
  18.    * phantom reference 的 get 方法永遠(yuǎn)返回 null   
  19.    */  
  20.   assertNull(phantomReference.get());  
  21.  } 

諸位可能要問(wèn), 一個(gè)永遠(yuǎn)返回 null 的 reference 要來(lái)何用,請(qǐng)注意構(gòu)造 PhantomReference 時(shí)的第二個(gè)參數(shù) ReferenceQueue(事實(shí)上 WeakReference & SoftReference 也可以有這個(gè)參數(shù)),
PhantomReference 唯一的用處就是跟蹤 referent何時(shí)被 enqueue 到 ReferenceQueue 中.

5. RererenceQueue

當(dāng)一個(gè) WeakReference 開(kāi)始返回 null 時(shí), 它所指向的對(duì)象已經(jīng)準(zhǔn)備被回收, 這時(shí)可以做一些合適的清理工作. 將一個(gè) ReferenceQueue 傳給一個(gè) Reference 的構(gòu)造函數(shù), 當(dāng)對(duì)象被回收時(shí), 虛擬機(jī)會(huì)自動(dòng)將這個(gè)對(duì)象插入到 ReferenceQueue 中, WeakHashMap 就是利用 ReferenceQueue 來(lái)清除 key 已經(jīng)沒(méi)有強(qiáng)引用的 entries.

  1. @Test  
  2. public void referenceQueue() throws InterruptedException {   
  3. Object referent = new Object();  
  4. ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();   
  5. WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue);   
  6.    
  7. assertFalse(weakReference.isEnqueued());   
  8. Reference<? extends Object> polled = referenceQueue.poll();   
  9. assertNull(polled);   
  10.    
  11. referent = null;   
  12. System.gc();   
  13.  
  14. assertTrue(weakReference.isEnqueued());   
  15. Reference<? extends Object> removed = referenceQueue.remove();   
  16. assertNotNull(removed);   
  17. }  
  18.  
  19.  @Test  
  20.  public void referenceQueue() throws InterruptedException {  
  21.   Object referent = new Object();    
  22.   ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();  
  23.   WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue);  
  24.     
  25.   assertFalse(weakReference.isEnqueued());  
  26.   Reference<? extends Object> polled = referenceQueue.poll();  
  27.   assertNull(polled);  
  28.     
  29.   referent = null;  
  30.   System.gc();  
  31.  
  32.   assertTrue(weakReference.isEnqueued());  
  33.   Reference<? extends Object> removed = referenceQueue.remove();  
  34.   assertNotNull(removed);  
  35.  } 


6.PhantomReferencevs WeakReference

PhantomReference有兩個(gè)好處, 其一, 它可以讓我們準(zhǔn)確地知道對(duì)象何時(shí)被從內(nèi)存中刪除, 這個(gè)特性可以被用于一些特殊的需求中(例如 Distributed GC,XWork 和 google-guice 中也使用 PhantomReference 做了一些清理性工作).

其二, 它可以避免 finalization 帶來(lái)的一些根本性問(wèn)題, 上文提到 PhantomReference 的唯一作用就是跟蹤 referent 何時(shí)被 enqueue 到 ReferenceQueue 中,但是 WeakReference 也有對(duì)應(yīng)的功能, 兩者的區(qū)別到底在哪呢 ?
這就要說(shuō)到 Object 的 finalize 方法, 此方法將在 gc 執(zhí)行前被調(diào)用, 如果某個(gè)對(duì)象重載了 finalize 方法并故意在方法內(nèi)創(chuàng)建本身的強(qiáng)引用,這將導(dǎo)致這一輪的 GC 無(wú)法回收這個(gè)對(duì)象并有可能
引起任意次 GC, ***的結(jié)果就是明明 JVM 內(nèi)有很多 Garbage 卻 OutOfMemory, 使用 PhantomReference 就可以避免這個(gè)問(wèn)題, 因?yàn)?PhantomReference 是在 finalize 方法執(zhí)行后回收的,也就意味著此時(shí)已經(jīng)不可能拿到原來(lái)的引用,也就不會(huì)出現(xiàn)上述問(wèn)題,當(dāng)然這是一個(gè)很極端的例子, 一般不會(huì)出現(xiàn).

7. 對(duì)比

Soft vs Weak vs Phantom References
Type Purpose Use When GCed Implementing Class
Strong Reference An ordinary reference. Keeps objects alive as long as they are referenced. normal reference. Any object not pointed to can be reclaimed. default
Soft Reference Keeps objects alive provided there’s enough memory. to keep objects alive even after clients have removed their references (memory-sensitive caches), in case clients start asking for them again by key. After a first gc pass, the JVM decides it still needs to reclaim more space. java.lang.ref.SoftReference
Weak Reference Keeps objects alive only while they’re in use (reachable) by clients. Containers that automatically delete objects no longer in use. After gc determines the object is only weakly reachable java.lang.ref.WeakReference 
java.util.WeakHashMap
Phantom Reference Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use offinalize()) Special clean up processing After finalization. java.lang.ref.PhantomReference


8. Java GC小結(jié)
 一般的應(yīng)用程序不會(huì)涉及到 Reference 編程, 但是了解這些知識(shí)會(huì)對(duì)理解Java GC 的工作原理以及性能調(diào)優(yōu)有一定幫助, 在實(shí)現(xiàn)一些基礎(chǔ)性設(shè)施比如緩存時(shí)也可能會(huì)用到, 希望本文能有所幫助.

【編輯推薦】

  1. 成為Java高手的重要過(guò)程
  2. Java GUI的發(fā)展和演化簡(jiǎn)史
  3. Java正則表達(dá)式工具類實(shí)例
  4. 用Java壓縮文件解決沒(méi)有中文問(wèn)題示例
  5. Java與C++語(yǔ)言在作用域上的差異淺析
責(zé)任編輯:彭凡 來(lái)源: javaeye
相關(guān)推薦

2017-11-15 19:30:08

Python內(nèi)存泄露循環(huán)引用

2015-11-02 17:20:00

Java弱引用

2024-12-16 16:10:31

2021-01-21 14:06:57

云計(jì)算

2023-12-25 09:30:41

Java垃圾回收

2009-09-09 09:36:25

Linq對(duì)象引用

2009-04-10 09:43:00

Java輸出流異常

2013-08-19 17:14:04

.Net強(qiáng)引用弱引用

2009-09-03 16:55:58

C#引用類型

2019-09-16 09:23:34

高并發(fā)編程CountDownLaCyclicBarri

2009-08-03 17:51:43

C#引用類型

2022-03-08 13:06:25

引用隊(duì)列jvm變量

2019-11-27 14:41:50

Java技術(shù)語(yǔ)言

2013-07-31 09:03:45

2009-12-30 15:58:19

Silverlight

2014-03-12 10:19:54

iOS對(duì)象

2015-05-14 15:38:40

javajava內(nèi)存泄露

2011-11-17 13:59:41

Java內(nèi)存管理內(nèi)存泄露

2009-08-19 16:39:44

C#值類型C#引用類型

2012-02-13 10:18:42

C++ 11
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 六月色婷| 欧美美女被c | 国产美女黄色片 | 三级黄色片在线播放 | 免费黄色大片 | 久久婷婷香蕉热狠狠综合 | 日韩成人在线播放 | 精品国产免费一区二区三区五区 | 1区2区3区视频 | 国产aⅴ精品| 国产电影一区二区三区爱妃记 | 99视频免费| 久久人人网 | 日本成人中文字幕在线观看 | 狠狠狠 | 99re在线免费视频 | 欧美日韩一区二区三区四区五区 | 久久专区| 亚洲综合在线视频 | 国产精品资源在线观看 | 国产91在线播放 | 成人亚洲| 午夜免费视频 | 国产高清一区二区三区 | 久久精品无码一区二区三区 | 国产ts人妖一区二区三区 | 黄色免费网 | 欧美日韩在线观看一区 | 色婷婷综合久久久久中文一区二区 | 欧美激情一区 | 亚洲欧美综合 | 一区二区国产精品 | 欧美精品一区二区三区在线 | 欧美精品1区2区3区 免费黄篇 | 野狼在线社区2017入口 | 成人av电影网 | 国产精品久久 | 青青草一区二区三区 | 成人免费视频网站在线看 | 精品国产乱码久久久久久蜜柚 | 日韩精品在线视频免费观看 |