java不同于c/c++绷跑,它不需要程序員自已來管理內(nèi)存(分配椅野,釋放內(nèi)存),java 會自己來管理內(nèi)存榜旦,比如銷毀某些不再被使用的對象幽七。這些回收的操作都有jvm后臺的GC線程自己完成,但是在一些情況下章办,程序員因為開發(fā)環(huán)境和需求等因素锉走,想介入這些回收的過程,至少是擁有一點點操控的權(quán)利藕届,JDK給予了用戶這樣的操作入口挪蹭,即四種引用類型。
強引用(Strong References)
強引用類型是我們平時寫代碼的時候最常用的引用休偶,比如
Sample sample = new Sample();
new就是強引用梁厉,是在java堆中開辟一段內(nèi)存空間,如果接下來
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源碼發(fā)現(xiàn)
private T referent; //這個才是軟引用疹尾, 只被jvm使用
軟引用在很多時候跟強引用一樣上忍,沒有人指向該對象的時候,對象就會被回收纳本,只不過窍蓝,還有一種會被回收的情況就是,如果堆內(nèi)存不足了繁成,GC會把軟引用也回收吓笙,不管有沒有人指向他。
軟引用的構(gòu)造方法還可以傳入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);
}
打印結(jié)果
ReferenceQueue這個隊列除了強引用之外祠墅,其他三種引用都可以用侮穿。
弱引用(Weak Reference)
GC進行垃圾收集的時候,如果一個對象只有弱引用指向它毁嗦,那么和沒有引用指向它是一樣的效果亲茅,GC都會回收他。也就是說,弱引用對象只能活到下一次GC克锣。
WeakReference<Sample> weakRef = new WeakReference<Sample>(sample, QUEUE);
虛引用(Phantom Reference)
虛引用的構(gòu)造方法必須強制傳入ReferenceQueue茵肃,因為在jvm回收前(重點: 對,就是回收前袭祟,軟引用和弱引用都是回收后)验残,會將PhantomReference對象加入ReferenceQueue中;還有一點就是PhantomReference.get()方法永遠返回空巾乳,不管對象有沒有被回收您没,就是說無法通過虛引用來獲取對象實例。那么胆绊,其實虛引用對于一個對象來說不起任何作用氨鹏,可有可無。
PhantomReference<Sample> phantomRef = new PhantomReference<>(sample, QUEUE);
那么為什么要引入虛引用压状,虛引用的唯一目的就是在一個對象實例被GC回收時仆抵,通過ReferenceQueue能獲得該對象被清理的消息通知。
本文整理自:http://blog.csdn.net/rodbate/article/details/72857447
感謝大佬V侄A统蟆!