java提供了4中引用類型,在垃圾回收的時候,都有本身的各自特色。java
爲何要區分這麼多引用呢,其實這和Java的GC有密切關係。緩存
public static void main(String[] args) { Object obj=new Object();//這樣定義就是一個強引用 Object obj2=obj;//也是一個強引用 obj=null; System.gc(); //不會被垃圾回收 System.out.println(obj2); }
/** * jvm配置配置小的內存,故意產生大的對象,致使OOM, * 驗證軟引用在內存足夠的先後是否被回收。 * 參數:-Xms:5M -Xmx:5M * @param args */ public static void main(String[] args) { Object obj=new Object();//這樣定義就是一個強引用 //軟引用須要使用java.lang.SoftReference來實現 //如今sf就是一個軟引用 SoftReference sf=new SoftReference(obj); obj=null; System.out.println("內存足夠軟引用引用的對象"+sf.get()); try { final byte[] bytes = new byte[8 * 1024 * 1024]; } catch (Exception e) { e.printStackTrace(); }finally { System.out.println("內存不夠:軟引用引用的對象:"+sf.get()); } }
結果:
jvm
* 若是一個對象只是被弱引用引用者,那麼只要發生GC,無論內存空間是否足夠,都會回收該對象。ide
public static void main(String[] args) { Object obj=new Object(); WeakReference wrf=new WeakReference(obj); obj=null; System.out.println("未發生GC以前"+wrf.get()); System.gc(); System.out.println("內存充足,發生GC以後"+wrf.get()); }
結果:函數
未發生GC以前java.lang.Object@2d363fb3 內存充足,發生GC以後null
WeakHashMap的鍵是「弱鍵」,也就是鍵的引用是一個弱引用。性能
public static void main(String[] args) { WeakHashMap<String,Integer> map=new WeakHashMap<>(); String key = new String("wekHashMap"); map.put(key,1); key=null; System.gc(); System.out.println(map); }
結果:map爲空了。
理論上咱們只是把引用變量key變成null了,"wekHashMap"字符串應該被Map中key引用啊,不該該被GC回收啊,
可是由於key是弱引用,GC回收的時候就忽略了這個引用,把對象當成垃圾收回了。spa
class User{ @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("我要被GC幹了!"); } } public static void main(String[] args) throws Exception { User user=new User(); ReferenceQueue<User> queue=new ReferenceQueue(); PhantomReference prf=new PhantomReference(user,queue); //啓動一個線程監控引用隊列的變化 new Thread(()->{ for(;;){ final Reference<? extends User> u = queue.poll(); if (u!=null){ System.out.println("有對象被加入到了引用隊列了!"+u); } } }).start(); user=null; //GC以前引用隊列爲空 System.out.println("GC以前"+queue.poll()); System.gc(); Thread.sleep(100); //GC以後引用隊列纔將對象放入 System.out.println("第一次GC以後"+queue.poll()); System.gc(); Thread.sleep(100); System.out.println("第二次GC以後"+queue.poll()); }
結果:線程
GC以前null 我要被GC幹了! 第一次GC以後null 有對象被加入到了引用隊列了!java.lang.ref.PhantomReference@549763fd 第二次GC以後java.lang.ref.PhantomReference@5aaa6d82
假若有一個應用須要讀取大量的本地圖片
每次讀取圖片都從硬盤讀取會影響性能。
一次所有加載到內存中,又可能形成內存溢出。
此時,可使用軟引用解決問題;
使用一個HashMap保存圖片的路徑和響應圖片對象關聯的軟引用之間的映射關係,
內存不足時,jvm會自動回收這些緩存圖片對象所佔用的空間,能夠避免OOM。code
Map<String,SoftReference<Bigmap>> imageCache=new HashMap<String,SoftReference<Bitmap>>();