強引用,軟引用,弱引用與虛引用
強引用:(StrongReference)
強引用指普通的對象引用
例如:
StringBuffer str = new StringBuffer("hello world");
局部變量str會被放到棧裏,而StringBuffer實例對象會被放在堆內,局部變量str指向堆內的StringBuffer對象,通過str可以操作該對象,那麽str就是StringBuffer的強引用
StringBuffer str1 = str;
當發生了這條語句,則
此時這兩個引用都是強引用
強引用具備如下特點:
1、通過強引用可以直接訪問目標對象
2、強引用所指向的對象在任何時候都不會被系統回收,虛擬機寧願拋出OOM(內存溢出)異常,也不會回收強引用所指向的對象
3、強引用可能導致內存泄漏(站著空間不釋放,積累的多了內存泄漏會導致內存溢出)
軟引用:(SoftReference)
軟引用描述一些還有用但非必需的對象,用java.lang.ref.SoftReference類表示,對於軟引用關聯的對象GC未必會一定會收,只有當內存資源緊張時,軟引用對象才會被回收,所以軟引用對象不會引起內存溢出(OOM)
1 import java.lang.ref.SoftReference; 2 3 //軟引用問題 4 public class SoftRef { 5 public static class User{ 6 publicint id; 7 public String name; 8 public User(int id,String name) { 9 this.id = id; 10 this.name = name; 11 } 12 @Override 13 public String toString() { 14 return "User [id=" + id + ", name=" + name + "]"; 15 } 16 1718 } 19 20 public static void main(String[] args) { 21 User u = new User(1,"吉米"); 22 //從強引用中獲取軟引用 23 SoftReference<User> sr = new SoftReference<User>(u); 24 //將強引用去除 25 u = null; 26 // get方法返回此引用對象的指示對象。用來獲取與軟引用關聯的對象的引用 27 System.out.println(sr.get()); 28 System.out.println("After GC"); 29 System.gc(); 30 System.out.println(sr.get()); 31 32 33 //這樣測試出來,軟引用可能不會被gc回收,此時需要模擬一下內存很緊張的狀態 34 byte b[] = new byte[1024*925*77]; 35 System.gc(); 36 System.out.println(sr.get()); 37 38 } 39 }
輸出:在-Xmx10m下輸出
User [id=1, name=吉米] //第一次從軟引用中獲取數據 After GC User [id=1, name=吉米] //GC沒有清除軟引用 null //由於內存緊張,軟引用被GC清理
此外,軟引用還可以附帶一個引用隊列,當對象可達性發生改時(由可達變為不可達,被回收),此時軟引用進入隊列,通過這個引用隊列,可以跟蹤對象的回收情況
弱引用:(WeakReference)
弱引用是比軟引用還弱的引用,在系統進行GC 時,只要發現弱引用,不管系統的堆空間是用了一點還是用了一大半,都會回收弱引用的對象。但是通常GC線程的優先級較低,因此不能立即發現持有弱引用的對象,在這種情況下弱引用對象可以存在較長的時間,一旦弱引用對象被回收,弱引用對象會加到一個註冊的引用隊列中去
弱引用代碼:
1 import java.lang.ref.WeakReference; 2 3 //弱引用 4 public class WeakRef { 5 public static class User{ 6 public int id; 7 public String name; 8 public User(int id, String name) { 9 this.id = id; 10 this.name = name; 11 } 12 @Override 13 public String toString() { 14 return "[id=" + id + ", name=" + name + "]"; 15 } 16 17 } 18 19 public static void main(String[] args) { 20 User u = new User(1,"geym"); 21 //創建軟引用對象 22 WeakReference<User> wr = new WeakReference<User>(u); 23 System.out.println(wr.get()); 24 System.gc(); 25 System.out.println("After GC:"); 26 System.out.println(wr.get()); 27 } 28 }
輸出:
[id=1, name=geym] After GC: null
根據軟引用和弱引用的特性,非常適合保存一些可有可無的緩存,如果這麽做,當系統內存空間不足時,會及時回收他們,不會導致內存溢出,當系統內存資源充足時,這些還存有可以存在相當長的時間,提升系統速度。
虛引用:(PhantomReference)(對象回收和跟蹤)
虛引用是所有引用中最弱的一個持有一個虛引用的對象,和沒有引用一樣,隨時都有可能會被垃圾回收器回收,當用虛引用的get方法去嘗試獲得強引用對象時總是會失敗,並且他必須和引用隊列一起使用,用於跟蹤垃圾回收過程,當垃圾回收器回收一個持有虛引用的對象時,在回收對象後,將這個虛引用對象加入到引用隊列中,用來通知應用程序垃圾的回收情況。
虛引用代碼:
1 import java.lang.ref.PhantomReference; 2 import java.lang.ref.ReferenceQueue; 3 4 public class PlantomRef { 5 public static class User{ 6 public int id; 7 public String name; 8 public User(int id,String name){ 9 this.id = id; 10 this.name = name; 11 } 12 @Override 13 public String toString() { 14 return "User [id=" + id + ", name=" + name + "]"; 15 } 16 17 } 18 19 public static void main(String[] args) { 20 User u = new User(1,"吉米"); 21 ReferenceQueue<? super User> queue = new ReferenceQueue<User>(); 22 PhantomReference<User> pr = new PhantomReference<User>(u,queue); 23 System.out.println(pr.get()); 24 25 } 26 27 28 29 }
輸出為null
由於虛引用可以跟蹤對象的回收時間,所以可以將一些資源的釋放操作放置在虛引用中執行和記錄
強引用,軟引用,弱引用與虛引用