軟引用是用來描述一些還有用,但非必需的對象。只被軟引用關聯著的對象,在系統將要發生內存溢出異常前,會把這些對象列進回收范圍之中進行第二次回收
,如果這次回收還沒有足夠的內存,才會拋出內存溢出異常。
軟引用通常用來實現內存敏感的緩存。比如: 高速緩存
就有用到軟引用。如果還有空閑內存,就可以暫時保留緩存,當內存不足時清理掉,這樣就保證了使用緩存的同時,不會耗盡內存。
垃圾回收器在某個時刻決定回收軟可達的對象的時候,會清理軟引用,并可選地把引用存放到一個引用隊列(Reference Queue)。
類似弱引用,只不過Java虛擬機盡量讓軟引用的存活時間長一些,迫不得已才清理。
啟動下面的代碼時候需加入如下參數:
-Xms10m -Xmx10m -XX:+PrintGCDetails
/**
* 軟引用的測試:內存不足即回收
*/
public class SoftReferenceTest {
public static class User {
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int id;
public String name;
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "] ";
}
}
public static void main(String[] args) {
//創建對象,建立軟引用
// SoftReference<User> userSoftRef = new SoftReference<User>(new User(1, "songhk"));
//上面的一行代碼,等價于如下的三行代碼
User u1 = new User(1, "young");
SoftReference<User> userSoftRef = new SoftReference<User>(u1);
u1 = null;//取消強引用
//從軟引用中重新獲得強引用對象
System.out.println(userSoftRef.get());
System.gc();
System.out.println("After GC:");
// //垃圾回收之后獲得軟引用中的對象
System.out.println(userSoftRef.get());//由于堆空間內存足夠,所以不會回收軟引用的可達對象。
//
try {
//讓系統認為內存資源緊張、不夠
byte[] b = new byte[1024 * 1024 * 7];
// byte[] b = new byte[1024 * 7168 - 635 * 1024];
} catch (Throwable e) {
e.printStackTrace();
} finally {
//再次從軟引用中獲取數據
System.out.println(userSoftRef.get());//在報OOM之前,垃圾回收器會回收軟引用的可達對象。
}
}
}