java不同于c/c++,它不需要程序員自已來管理內存(分配,釋放內存),java 會自己來管理內存,比如銷毀某些不再被使用的對象。這些回收的操作都有jvm后臺的GC線程自己完成,但是在一些情況下,程序員因為開發環境和需求等因素,想介入這些回收的過程,至少是擁有一點點操控的權利,JDK給予了用戶這樣的操作入口,即四種引用類型。
強引用(Strong References)
強引用類型是我們平時寫代碼的時候最常用的引用,比如
Sample sample = new Sample();
new就是強引用,是在java堆中開辟一段內存空間,如果接下來
sample = null;
將引用指向一個空指針或者指向其他對象,那么剛才new出來的對象就沒有引用指向他,在GC進行可達性分析得時候就沒法找到鏈路能到達它,于是他會被回收掉。
軟引用(Soft References)
Sample sample = new Sample(); //首先用強引用sample指向該對象
/**使用java軟引用類SoftReference
* 需要注意的是,softRef這個引用也是強引用,它是指向SoftReference這個對象的
* 真正的軟引用被包裝在了softRef中
*/
SoftReference<Sample> softRef = new SoftReference<Sample>(sample);
//查看java.lang.Reference源碼發現
private T referent; //這個才是軟引用, 只被jvm使用
軟引用在很多時候跟強引用一樣,沒有人指向該對象的時候,對象就會被回收,只不過,還有一種會被回收的情況就是,如果堆內存不足了,GC會把軟引用也回收,不管有沒有人指向他。
軟引用的構造方法還可以傳入ReferenceQueue,如下
private static final ReferenceQueue<Sample> QUEUE = new ReferenceQueue<>();
SoftReference<Sample> softRef = new SoftReference<Sample>(sample, QUEUE);
這個隊列的作用就是當jvm回收某個軟引用對象之后會將該SoftReference對象(例子中的softRef對象)添加進這個隊列,因此我們就知道這個對象啥時候被回收了,具體使用如下:
//while外面可以用定時器包裝
while (true) {
Reference<? extends Sample> poll = QUEUE.poll();
if (poll != null) {
//poll是softRef對象地址,不是referent地址
System.out.println("--- 軟引用對象被jvm回收了 ---- " + poll);
}
打印結果
ReferenceQueue這個隊列除了強引用之外,其他三種引用都可以用。
弱引用(Weak Reference)
GC進行垃圾收集的時候,如果一個對象只有弱引用指向它,那么和沒有引用指向它是一樣的效果,GC都會回收他。也就是說,弱引用對象只能活到下一次GC。
WeakReference<Sample> weakRef = new WeakReference<Sample>(sample, QUEUE);
虛引用(Phantom Reference)
虛引用的構造方法必須強制傳入ReferenceQueue,因為在jvm回收前(重點: 對,就是回收前,軟引用和弱引用都是回收后),會將PhantomReference對象加入ReferenceQueue中;還有一點就是PhantomReference.get()方法永遠返回空,不管對象有沒有被回收,就是說無法通過虛引用來獲取對象實例。那么,其實虛引用對于一個對象來說不起任何作用,可有可無。
PhantomReference<Sample> phantomRef = new PhantomReference<>(sample, QUEUE);
那么為什么要引入虛引用,虛引用的唯一目的就是在一個對象實例被GC回收時,通過ReferenceQueue能獲得該對象被清理的消息通知。
本文整理自:http://blog.csdn.net/rodbate/article/details/72857447
感謝大佬?。?!