jvm 07-java引用型別
阿新 • • 發佈:2018-11-26
java引用型別
- 強引用:當記憶體不足的時候,都不會進行空間回收,最終JVM丟擲OutOfMemoryError
- 軟引用:當記憶體不足的時候,進行物件的回收處理,往往用於快取記憶體中
- 弱引用:不管記憶體是否緊張,只要GC執行都會回收
- 幽靈引用:和沒引用一樣。
強引用
- JVM預設支援模式
- 在引用期間內,如果該堆記憶體被指定的棧記憶體有聯絡,那該物件就無法被GC所回收
- 一旦出現記憶體不足,就會出現OutOfMemoryError異常
- 正因為強引用具備記憶體分配異常問題,因此儘量少例項化物件
測試程式:
package cn.liang.jvm; import static org.hamcrest.CoreMatchers.nullValue; import java.lang.ref.SoftReference; public class referenceType2 { public static void main(String[] args) { Object object = new Object(); Object ref = object; object = null; System.out.println("記憶體充足時進行gc回收:"); System.gc(); System.out.println(ref); System.out.println("記憶體不足時進行gc回收:"); try { String string = "liangjingfu"; while (true) { string += string + string; string.intern(); } } catch (Throwable e) { } System.out.println(ref); } }
輸出結果:
記憶體充足時進行gc回收: [email protected] 記憶體不足時進行gc回收: [email protected]
軟引用
- 在許多的開源元件中,往往會使用軟引用作為快取元件出現
- 軟引用不足時回收,不充足時不回收
- 軟引用需要一個單獨的類來實現控制:java.lang.ref.SoftReference
- 建構函式:public SoftReference(T referent)
- 取出資料:public T get();
測試程式:
package cn.liang.jvm; import static org.hamcrest.CoreMatchers.nullValue; import java.lang.ref.SoftReference; public class referenceType2 { public static void main(String[] args) { Object object = new Object(); SoftReference<Object> ref = new SoftReference<Object>(object); object = null; System.out.println("記憶體充足時進行gc回收:"); System.gc(); System.out.println(ref.get()); System.out.println("記憶體不足時進行gc回收:"); try { String string = "liangjingfu"; while (true) { string += string + string; string.intern(); } } catch (Throwable e) { } System.out.println(ref.get()); } }
輸出結果:
記憶體充足時進行gc回收: [email protected] 記憶體不足時進行gc回收: null
弱引用:
- 只要一進行GC處理,那麼所引用的物件將會立即回收
- 弱引用需要使用Map介面的子類:java.util.WeakHashMap
- java.lang.ref包中存在一個WeakReference子類
測試程式1:
package cn.liang.jvm; import java.util.Map; import java.util.WeakHashMap; public class referenceType3 { public static void main(String[] args) { String keyString = new String("name"); String valueString = new String("liang"); Map<String, String> map = new WeakHashMap<String, String>(); map.put(keyString, valueString); keyString = null; System.out.println("記憶體進行gc回收前:"); System.out.println(map); System.out.println("記憶體進行gc回收後:"); System.gc(); System.out.println(map); } }
輸出結果:
記憶體進行gc回收前: {name=liang} 記憶體進行gc回收後: {}
測試程式2:
package cn.liang.jvm; import java.lang.ref.WeakReference; import java.util.Map; import java.util.WeakHashMap; public class referenceType3 { public static void main(String[] args) { String keyString = new String("liang"); WeakReference<String> reference = new WeakReference<String>(keyString); keyString = null; System.out.println("記憶體進行gc回收前:"); System.out.println(reference.get()); System.gc(); System.out.println("記憶體進行gc回收後:"); System.out.println(reference.get()); } }
輸出結果:
記憶體進行gc回收前: liang 記憶體進行gc回收後: null
引用佇列
- 主要是儲存那些準備被回收的物件
- 所有的物件的回收掃描都是從根物件開始的
- 引用路徑的設定即確定好哪些物件可以被回收後,設定相應的引用強度
- 引用佇列可避免非強引用物件所帶來的記憶體引用問題,該物件被回收後會自動儲存
- 找到物件5有兩個路徑:
- 物件1 --> 物件5(強 + 軟)
- 物件2 --> 物件5(強 + 弱)
測試程式:
package cn.liang.jvm; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.Map; import java.util.WeakHashMap; public class referenceType4 { public static void main(String[] args) throws Exception { Object obj = new Object(); ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); WeakReference<Object> reference = new WeakReference<Object>(obj,queue); System.out.println("記憶體進行gc回收前:"); System.out.println(queue.poll()); obj = null; System.gc(); Thread.sleep(100); System.out.println("記憶體進行gc回收後,物件儲存:"); System.out.println(queue.poll()); } }
輸出結果:
記憶體進行gc回收前: null 記憶體進行gc回收後,物件儲存: [email protected]
幽靈引用
- 永遠取不了的資料
測試程式:
package cn.liang.jvm; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.Map; import java.util.WeakHashMap; public class referenceType5 { public static void main(String[] args) throws Exception { Object obj = new Object(); ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); PhantomReference<Object> reference = new PhantomReference<Object>(obj,queue); System.gc(); System.out.println("物件讀取:"); System.out.println(reference.get()); System.out.println("物件儲存後讀取:"); System.out.println(queue.poll()); } }
輸出結果:
物件讀取: null 物件儲存後讀取: null