【JVM】如何理解強引用、軟引用、弱引用、虛引用?_潭子電動車

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

整體架構

強引用

強引用是默認支持,當內存不足的時候,JVM開始垃圾回收,對於強引用的對象,就算是出現了OOM也不會回收對象。

強引用是最常見的普通對象引用,只要還有強引用指向對象,對象就存活,垃圾回收器不會處理存活對象。一般把一個對象賦給一個引用變量,這個引用變量就是強引用。當一個對象被強引用變量所引用,它就處於可達狀態,是不會被垃圾回收的,即使之後都不會再用到了,也不會回收。因此強引用是造成Java內存泄漏的主要原因之一

關於Java內存泄漏的詳細內容,可以參考這篇博客:https://blog.csdn.net/m0_38110132/article/details/81986334。

對於一個普通對象,如果沒有其他引用關係,只要超過了引用的作用域或者顯式地將相應的強引用賦值為null,一般認為就是可以被垃圾回收了。(具體的回收時機看垃圾回收策略)

下例中,b就是強引用。

1     public static void main(String[] args) {
2         Object a = new Object();
3         Object b = a;
4         a = null;
5         System.out.println(b);//java.lang.Object@4554617c
6     }

軟引用

軟引用是一種相對強引用弱化了一些的引用,用java.lang.ref.SoftReference實現,可以讓對象豁免一些垃圾收集。當系統內存充足的時候,不會被回收;當系統內存不足的時候,會被回收。

軟引用一般用於對內存敏感的程序中,比如高速緩存。

 1 import java.lang.ref.SoftReference;
 2 
 3 public class SoftReferenceDemo {
 4     public static void main(String[] args) {
 5         Object a = new Object();
 6         SoftReference<Object> softReference = new SoftReference<>(a);//軟引用
 7         //a和軟引用指向同一個對象
 8         System.out.println(a);//java.lang.Object@4554617c
 9         System.out.println(softReference.get());//java.lang.Object@4554617c
10 
11         //內存夠用,軟引用不會被回收
12         a = null;
13         System.gc();//內存夠用不會自動gc,手動喚醒gc
14         System.out.println(a);//null
15         System.out.println(softReference.get());//java.lang.Object@4554617c
16 
17         //內存不夠用時
18         try{
19             //配置Xms和Xmx為5MB
20             byte[] bytes = new byte[1024*1024*30];//設置30MB超內存
21         }catch (Throwable e){
22             e.printStackTrace();
23         }finally {
24             System.out.println(a);//null
25             System.out.println(softReference.get());//null
26         }
27     }
28 }

使用場景

一個應用需要讀取大量的本地圖片,如果每次讀取都從硬盤讀取會嚴重影響性能,如果一次性全部加載到內存,內存可能會溢出。

可以使用軟引用解決這個問題,使用一個HashMap來保存圖片路徑和圖片對象管理的軟引用之間的映射關係,內存不足時,JVM會自動回收緩存圖片對象的佔用空間,有效地避免了OOM(Out Of Memory)問題。

Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>

弱引用

弱引用需要用java.lang.ref.WeakReference實現,它比軟引用的生存期更短,對於弱引用的對象來說,只要垃圾回收機制一運行,不管JVM的內存空間是否夠,都會回收該對象的佔用內存。

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

 1 import java.lang.ref.WeakReference;
 2 
 3 public class SoftReferenceDemo {
 4     public static void main(String[] args) {
 5         Object a = new Object();
 6         WeakReference<Object> softReference = new WeakReference<>(a);//軟引用
 7         //a和弱引用指向同一個對象
 8         System.out.println(a);//java.lang.Object@4554617c
 9         System.out.println(softReference.get());//java.lang.Object@4554617c
10 
11         //內存夠用,弱引用也會被回收
12         a = null;
13         System.gc();//內存夠用不會自動gc,手動喚醒gc
14         System.out.println(a);//null
15         System.out.println(softReference.get());//null
16     }
17 }

關於WeakHashMap

 1     public static void weakHashMapTest() {
 2         Integer key = new Integer(1);
 3         String value = "李四";
 4         Map<Integer,String> weakHashMap = new WeakHashMap();
 5         weakHashMap.put(key, value);
 6         System.out.println(weakHashMap);//{1=李四}
 7         key = null;
 8         System.gc();
 9         System.out.println(weakHashMap);//{}
10     }
11 
12     public static void hashMapTest() {
13         HashMap<Integer,String> map = new HashMap<>();
14         Integer key = 1;
15         String value = "張三";
16         map.put(key,value);
17         System.out.println(map);//{1=張三}
18         key = null;
19         System.gc();
20         System.out.println(map);//{1=張三}
21     }

在HashMap中,鍵被置為null,喚醒gc后,不會垃圾回收鍵為null的鍵值對。但是在WeakHashMap中,鍵被置為null,喚醒gc后,鍵為null的鍵值對會被回收。

虛引用

虛引用要通過java.lang.ref.PhantomReference類來實現,虛引用不會決定對象的生命周期,如果一個對象只有虛引用,就相當於沒有引用,在任何時候都可能會被垃圾回收器回收。它不能單獨使用也不能訪問對象,虛引用必須和引用隊列聯合使用

虛引用的主要作用是跟蹤對象被垃圾回收的狀態,僅僅是提供一種確保對象被finalize以後,做某些事情的機制。

PhantomReference的get方法總是返回null,因此無法訪問對應的引用對象,設置虛引用關聯唯一的目的是在對象被收集器回收的時候收到一個系統通知,或者後續添加進一步的處理。Java允許使用finalize()方法在垃圾回收器將對象從內存中清理出去之前做一些必要的清理工作。【例如實現一個監控對象的通知機制】

引用隊列

WeakReference和ReferenceQueue的聯合使用效果:

 1     public static void weakReferenceTest() {
 2         Object a = new Object();
 3         ReferenceQueue<Object> queue = new ReferenceQueue<>();
 4         WeakReference<Object> weakReference = new WeakReference<>(a,queue);
 5         System.out.println(a);//java.lang.Object@4554617c
 6         System.out.println(weakReference.get());//java.lang.Object@4554617c
 7         System.out.println(queue.poll());//null
 8         System.out.println("-------------------");
 9         a = null;
10         System.gc();
11         System.out.println(a);//null
12         System.out.println(weakReference.get());//null
13         //虛引用在回收之前被加入到了引用隊列中
14         System.out.println(queue.poll());//java.lang.ref.WeakReference@74a14482
15     }

PhantomReference和ReferenceQueue的聯合使用效果:

 1     public static void phantomReferenceTest() {
 2         Object a = new Object();
 3         ReferenceQueue<Object> queue = new ReferenceQueue<>();
 4         PhantomReference<Object> phantomReference = new PhantomReference<>(a,queue);
 5         System.out.println(a);//java.lang.Object@4554617c
 6         System.out.println(phantomReference.get());//null
 7         System.out.println(queue.poll());//null
 8         System.out.println("-------------------");
 9         a = null;
10         System.gc();
11         System.out.println(a);//null
12         System.out.println(phantomReference.get());//null
13         //引用在回收之前被加入到了引用隊列中
14         System.out.println(queue.poll());//java.lang.ref.WeakReference@74a14482
15     }

總結

強引用:不回收。

軟引用:內存不夠就回收。

弱引用:一定回收。

虛引用:一定回收,get出來就是null,引用形同虛設,主要和引用隊列聯合使用,在finalize之前會被放到引用隊列中。

與根對象沒有引用關係的:引用不可達,一定回收。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。