WeakReference弱引用概述
http://www.cnblogs.com/xrq730/p/4836700.html,關於Java的四種引用狀態具體請參看此文
Java里一個對象obj被創建時,被放在堆里。當GC運行的時候,發現沒有任何引用指向obj,那么就會回收obj對象的堆內存空間。
但是現實的情況時,寫代碼的時候,往往通過把所有指向某個對象的引用置空來保證這個對象在下次GC運行的時候被回收:
Object obj = new Object();
obj = null;
這種方式說可以吧,也不是不可以,但是對於程序員來說,這是一件繁瑣而且未被自動回收理念的。手動置空不應該需要程序員來做的,因為對於一個簡單的對象而言,當調用它的方法執行完畢,引用會自動從棧中彈出,這樣下一次GC的時候就會自動回收這塊內存了。
但是有例外。比如說緩存,由於緩存對象是程序需要的,那么只要程序正在運行,緩存中的引用是不會被GC的,隨着緩存中的引用越來越多,GC無法回收的對象也越來越多,無法被自動回收。當這些對象需要被回收時,回收這些對象的任務只有交給程序員了,然而這卻違背了GC的本質----自動回收。
所以Java中引入了弱引用WeakReference。
WeakReference弱引用示例
下面演示一下WeakReference簡單的使用,首先定義一個實體類:
public class Car { private double price; private String color; public Car(double price, String color) { this.price = price; this.color = color; } public double getPrice() { return price; } public String getColor() { return color; } public String toString() { return "This car is a " + this.color + " car, costs $" + price; } }
一般使用WeakReference的時候都會定義一個類繼承自WeakReference,在這個類中再定義一些別的屬性,這里就不定義別的屬性了:
public class WeakReferenceCar extends WeakReference<Car> { public WeakReferenceCar(Car car) { super(car); } } public class WeakReferenceCar extends WeakReference<Car> { public WeakReferenceCar(Car car) { super(car); } }
main函數調用一下,當然為了更清楚地看到GC的效果,設置虛擬機參數"-XX:+PrintGCDetails":
public static void main(String[] args) { Car car = new Car(2000.0, "red"); WeakReferenceCar wrc = new WeakReferenceCar(car); wrc.setStr("111"); int i = 0; while (true) { if (wrc.get() != null) { i++; System.out.println("WeakReferenceCar's Car is alive for " + i + ", loop - " + wrc); } else { System.out.println("WeakReferenceCar's Car has bean collected"); break; } } }
看一下運行結果:
WeakReferenceCar's Car is alive for 22880, loop - com.xrq.test14.WeakReferenceCar@5d888759 WeakReferenceCar's Car is alive for 22881, loop - com.xrq.test14.WeakReferenceCar@5d888759 WeakReferenceCar's Car is alive for 22882, loop - com.xrq.test14.WeakReferenceCar@5d888759 WeakReferenceCar's Car is alive for 22883, loop - com.xrq.test14.WeakReferenceCar@5d888759 WeakReferenceCar's Car is alive for 22884, loop - com.xrq.test14.WeakReferenceCar@5d888759 [GC [PSYoungGen: 16400K->256K(18688K)] 16400K->256K(61440K), 0.0002863 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] WeakReferenceCar's Car is alive for 22885, loop - com.xrq.test14.WeakReferenceCar@5d888759 WeakReferenceCar's Car has bean collected Heap PSYoungGen total 18688K, used 899K [0x0000000034180000, 0x0000000035650000, 0x0000000048f80000) eden space 16064K, 4% used [0x0000000034180000,0x0000000034220c30,0x0000000035130000) from space 2624K, 9% used [0x00000000353c0000,0x0000000035400000,0x0000000035650000) to space 2624K, 0% used [0x0000000035130000,0x0000000035130000,0x00000000353c0000) PSOldGen total 42752K, used 0K [0x000000000a580000, 0x000000000cf40000, 0x0000000034180000) object space 42752K, 0% used [0x000000000a580000,0x000000000a580000,0x000000000cf40000) PSPermGen total 21248K, used 3016K [0x0000000005180000, 0x0000000006640000, 0x000000000a580000) object space 21248K, 14% used [0x0000000005180000,0x0000000005472318,0x0000000006640000)
看到22884次循環之后,WeakReferenceCar關聯的對象Car被回收掉了,注意是弱引用關聯的對象car被回收,而不是弱引用本身wrc被回收。
其他
1、除了弱引用,還有軟引用。SoftReference(軟引用)和WeakReference的區別在於,假如下次GC的時候,發現內存沒有溢出,則不會回收SoftReference關聯的對象,但是對於WeakReference,在下一次GC的時候,一定會回收,無論內存是否滿。像緩存,其實最適合的個人認為應該是SoftReference,因為緩存里面的數據是運行時會用到的,能不回收就盡量不要去回收它們,而等到內存實在不夠的時候再去回收
2、WeakReference的父類Reference中有一個變量queue,是ReferenceQueue類型的。WeakReference中的構造函數中有一個兩個參數的構造函數,其中第二個參數就是這個ReferenceQueue,表示在WeakReference指向的對象被回收之后,可以利用ReferenceQueue來保存被回收的對象