1. 程式人生 > >強引用,軟引用,弱引用與虛引用

強引用,軟引用,弱引用與虛引用

img stringbu ride 分享圖片 tro 通過 一個 null 情況

強引用:(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         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 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

由於虛引用可以跟蹤對象的回收時間,所以可以將一些資源的釋放操作放置在虛引用中執行和記錄

強引用,軟引用,弱引用與虛引用