Java的四种引用,强弱软虚,用到的场景(转+补充)
Q1:引用隊(duì)列是什么?如何使用?使用的場(chǎng)景有哪些?
A1:oracle的api文檔的描述:
https://docs.oracle.com/javase/7/docs/api/java/lang/ref/ReferenceQueue.htmlReference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.
當(dāng)對(duì)象的可及性的改變被GC發(fā)現(xiàn)時(shí),與之相關(guān)聯(lián)的(registered)的reference object會(huì)被加入該隊(duì)列。
?
Q2:java的heap是什么?
A2:如圖所示,Heap和Stack分別負(fù)責(zé)存儲(chǔ)不同類型的數(shù)據(jù)。
Stack區(qū)用于存儲(chǔ)基本數(shù)據(jù)類型和對(duì)象的引用;而Heap區(qū)存儲(chǔ)對(duì)象的實(shí)例。
Stack區(qū)的讀寫很快但缺點(diǎn)是數(shù)據(jù)的生存期和大小都是固定的,而Heap則可以動(dòng)態(tài)申請(qǐng)內(nèi)存。
具體內(nèi)容很多,以后單獨(dú)寫上。
?
在Java里, 當(dāng)一個(gè)對(duì)象o被創(chuàng)建時(shí), 它被放在Heap里. 當(dāng)GC運(yùn)行的時(shí)候, 如果發(fā)現(xiàn)沒有任何引用指向o, o就會(huì)被回收以騰出內(nèi)存空間. 或者換句話說, 一個(gè)對(duì)象被回收, 必須滿足兩個(gè)條件:
?
強(qiáng)引用:
?
強(qiáng)引用不會(huì)被GC回收,并且在java.lang.ref里也沒有實(shí)際的對(duì)應(yīng)類型,平時(shí)工作接觸的最多的就是強(qiáng)引用。Object obj = new Object();這里的obj引用便是一個(gè)強(qiáng)引用。如果一個(gè)對(duì)象具有強(qiáng)引用,那就類似于必不可少的生活用品,垃圾回收器絕不會(huì)回收它。 當(dāng)內(nèi)存空間不足,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足問題。
?
軟引用:如果一個(gè)對(duì)象只具有軟引用,那就類似于可有可物的生活用品。如果內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它,如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它,該對(duì)象就可以被程序使用。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存。軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果軟引用所引用的對(duì)象被垃圾回收,Java虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。
?
弱引用:
?
弱引用(weak reference)在強(qiáng)度上弱于軟引用,通過類WeakReference來表示。它的作用是引用一個(gè)對(duì)象,但是并不阻止該對(duì)象被回收。如果使用一個(gè)強(qiáng)引用的話,只要該引用存在,那么被引用的對(duì)象是不能被回收的。弱引用則沒有這個(gè)問題。在垃圾回收器運(yùn)行的時(shí)候,如果一個(gè)對(duì)象的所有引用都是弱引用的話,該對(duì)象會(huì)被回收。弱引用的作用在于解決強(qiáng)引用所帶來的對(duì)象之間在存活時(shí)間上的耦合關(guān)系。弱引用最常見的用處是在集合類中,尤其在哈希表中。哈希表的接口允許使用任何Java對(duì)象作為鍵來使用。當(dāng)一個(gè)鍵值對(duì)被放入到哈希表中之后,哈希表對(duì)象本身就有了對(duì)這些鍵和值對(duì)象的引用。如果這種引用是強(qiáng)引用的話,那么只要哈希表對(duì)象本身還存活,其中所包含的鍵和值對(duì)象是不會(huì)被回收的。如果某個(gè)存活時(shí)間很長(zhǎng)的哈希表中包含的鍵值對(duì)很多,最終就有可能消耗掉JVM中全部的內(nèi)存。
?
對(duì)于這種情況的解決辦法就是使用弱引用來引用這些對(duì)象,這樣哈希表中的鍵和值對(duì)象都能被垃圾回收。Java中提供了WeakHashMap來滿足這一常見需求。
?
虛引用:
?
在介紹幽靈引用之前,要先介紹Java提供的對(duì)象終止化機(jī)制(finalization)。在Object類里面有個(gè)finalize方法,其設(shè)計(jì)的初衷是在一個(gè)對(duì)象被真正回收之前,可以用來執(zhí)行一些清理的工作。因?yàn)?span style="line-height:normal;font-family:Helvetica;">Java并沒有提供類似C++的析構(gòu)函數(shù)一樣的機(jī)制,就通過 finalize方法來實(shí)現(xiàn)。但是問題在于垃圾回收器的運(yùn)行時(shí)間是不固定的,所以這些清理工作的實(shí)際運(yùn)行時(shí)間也是不能預(yù)知的。幽靈引用(phantom reference)可以解決這個(gè)問題。在創(chuàng)建幽靈引用PhantomReference的時(shí)候必須要指定一個(gè)引用隊(duì)列。當(dāng)一個(gè)對(duì)象的finalize方法已經(jīng)被調(diào)用了之后,這個(gè)對(duì)象的幽靈引用會(huì)被加入到隊(duì)列中。通過檢查該隊(duì)列里面的內(nèi)容就知道一個(gè)對(duì)象是不是已經(jīng)準(zhǔn)備要被回收了。
?
幽靈引用及其隊(duì)列的使用情況并不多見,主要用來實(shí)現(xiàn)比較精細(xì)的內(nèi)存使用控制,這對(duì)于移動(dòng)設(shè)備來說是很有意義的。程序可以在確定一個(gè)對(duì)象要被回收之后,再申請(qǐng)內(nèi)存創(chuàng)建新的對(duì)象。通過這種方式可以使得程序所消耗的內(nèi)存維持在一個(gè)相對(duì)較低的數(shù)量。
?
?
相關(guān)鏈接:
http://blog.csdn.net/weizaishouex2010/article/details/49002913
http://stackoverflow.com/questions/14450538/using-javas-referencequeue(stackoverflow上講的弱引用和引用隊(duì)列的應(yīng)用場(chǎng)景)
轉(zhuǎn)載于:https://www.cnblogs.com/Russel/p/5944735.html
總結(jié)
以上是生活随笔為你收集整理的Java的四种引用,强弱软虚,用到的场景(转+补充)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无法使用此电子邮件地址。请选择其他电子邮
- 下一篇: 常用的相似度计算