Java內(nèi)存回收機(jī)制
一、Java對(duì)象在內(nèi)存引用狀態(tài)
內(nèi)存泄露:程序運(yùn)行過(guò)程中,會(huì)不斷分配內(nèi)存空間,那些不再使用的內(nèi)存空間應(yīng)該即時(shí)回收它們,從而保證系統(tǒng)可以再次使用這些內(nèi)存,如果存在無(wú)用的內(nèi)存沒(méi)有被回收回來(lái),這就是內(nèi)存泄漏.
(1)強(qiáng)引用
這是java程序中最常見(jiàn)的引用方式,程序創(chuàng)建一個(gè)對(duì)象,并把這個(gè)對(duì)象賦給一個(gè)引用變量,這個(gè)引用變量就是強(qiáng)引用.java程序可通過(guò)強(qiáng)引用來(lái)訪問(wèn)實(shí)際的對(duì)象。當(dāng)一個(gè)對(duì)象被一個(gè)或一個(gè)以上的強(qiáng)引用變量引用時(shí),它處于可達(dá)狀態(tài),它不可能被系統(tǒng)垃圾回收機(jī)制回收。
強(qiáng)引用是Java編程中廣泛使用的引用類(lèi)型,被強(qiáng)引用所引用的Java對(duì)象絕不會(huì)被垃圾回收機(jī)制回收,即使系統(tǒng)內(nèi)存緊張;即使有些Java對(duì)象以后永遠(yuǎn)也不會(huì)被用到,JVM也不會(huì)回收被強(qiáng)引用所引用的Java對(duì)象.
由于JVM肯定不會(huì)回收強(qiáng)引用所引用的JAVA對(duì)象,因此強(qiáng)引用是造成JAVA內(nèi)存泄漏的主要原因。
如 ReceiptBean rb=new ReceiptBean(); rb就代表了一種強(qiáng)引用的方式
(2)軟引用
軟引用需要通過(guò)SoftReference類(lèi)來(lái)實(shí)現(xiàn),當(dāng)一個(gè)對(duì)象只具有軟引用時(shí),它可能被垃圾回收機(jī)制回收。對(duì)于只有軟引用的對(duì)象而言,當(dāng)系統(tǒng)內(nèi)存空間足夠時(shí),它不會(huì)被系統(tǒng)回收,程序也可以使用該對(duì)象;當(dāng)系統(tǒng)內(nèi)存空間不足時(shí),系統(tǒng)將回收它.
軟引用通常用在對(duì)內(nèi)存敏感的程序中,軟引用是強(qiáng)引用很好的替代。對(duì)于軟引用,當(dāng)系統(tǒng)內(nèi)存空間充足時(shí),軟引用與強(qiáng)引用沒(méi)有太大的區(qū)別,當(dāng)系統(tǒng)內(nèi)存空間不足時(shí),被軟引用所引用的JAVA對(duì)象可以被垃圾回收機(jī)制回收,從而避免系統(tǒng)內(nèi)存不足的異常.
當(dāng)程序需要大量創(chuàng)建某個(gè)類(lèi)的新對(duì)象,而且有可能重新訪問(wèn)已創(chuàng)建老對(duì)象時(shí),可以充分使用軟引用來(lái)解決內(nèi)存緊張的問(wèn)題。
例如需要訪問(wèn)1000個(gè)Person對(duì)象,可以有兩種方式
方法一 依次創(chuàng)建1000個(gè)對(duì)象,但只有一個(gè)Person引用指向最后一個(gè)Person對(duì)象
方法二 定義一個(gè)長(zhǎng)度為1000個(gè)的Person數(shù)組,每個(gè)數(shù)組元素引用一個(gè)Person對(duì)象.
對(duì)于方法一,弱點(diǎn)很明顯,程序不允許需要重新訪問(wèn)前面創(chuàng)建的Person對(duì)象,即使這個(gè)對(duì)象所占的空間還沒(méi)有被回收。但已經(jīng)失去了這個(gè)對(duì)象的引用,因此也不得不重新創(chuàng)建一個(gè)新的Person對(duì)象(重新分配內(nèi)存),而那個(gè)已有的Person對(duì)象(完整的,正確的,可用的)則只能等待垃圾回收
對(duì)于方法二,優(yōu)勢(shì)是可以隨時(shí)重新訪問(wèn)前面創(chuàng)建的每個(gè)Person對(duì)象,但弱點(diǎn)也有,如果系統(tǒng)堆內(nèi)存空間緊張,而1000個(gè)Person對(duì)象都被強(qiáng)引用引著,垃圾回收機(jī)制也不可能回收它們的堆內(nèi)存空間,系統(tǒng)性能將變成非常差,甚至因此內(nèi)存不足導(dǎo)致程序中止。
如果用軟引用則是一種較好的方案,當(dāng)堆內(nèi)存空間足夠時(shí),垃圾回收機(jī)制不會(huì)回收Person對(duì)象,可以隨時(shí)重新訪問(wèn)一個(gè)已有的Person對(duì)象,這和普通的強(qiáng)引用沒(méi)有任何區(qū)別。但當(dāng)heap堆內(nèi)存空間不足時(shí),系統(tǒng)也可以回收軟引用引用的Person對(duì)象,從而提高程序運(yùn)行性能,避免垃圾回收.
當(dāng)程序使用強(qiáng)引用時(shí),無(wú)論系統(tǒng)堆內(nèi)存如何緊張,JVM垃圾回收機(jī)制都不會(huì)回收被強(qiáng)引用所引用的Java對(duì)象,因此最后導(dǎo)致程序因內(nèi)存不足而中止。但如果把強(qiáng)引用改為軟引用,就完成可以避免這種情況,這就是軟引用的優(yōu)勢(shì)所在.
(3)弱引用
弱引用與軟引用有點(diǎn)相似,區(qū)別在于弱引用所引用對(duì)象的生存期更短。弱引用通過(guò)WeakReference類(lèi)實(shí)現(xiàn),弱引用和軟引用很像,但弱引用的引用級(jí)別更低。對(duì)于只有弱引用的對(duì)象而言,當(dāng)系統(tǒng)垃圾回收機(jī)制運(yùn)行時(shí),不管系統(tǒng)內(nèi)存是否足夠,總會(huì)回收該對(duì)象所占用的內(nèi)存。當(dāng)然,并不是說(shuō)當(dāng)一個(gè)對(duì)象只有弱引用時(shí),它就會(huì)立即被回收,正如那些失去引用的對(duì)象一樣,必須等到系統(tǒng)垃圾回收機(jī)制運(yùn)行時(shí)才會(huì)被回收.
總結(jié)說(shuō)明:
1.弱引用具有很大的不確定性,因?yàn)槊看卫厥諜C(jī)制執(zhí)行時(shí)都會(huì)回收弱引用所引用的對(duì)象,而垃圾回收機(jī)制的運(yùn)行又不受程序員的控制,因此程序獲取弱引用所引用的java對(duì)象時(shí)必須小心空指針異常,通過(guò)弱引用所獲取的java對(duì)象可能是null
2.由于垃圾回收的不確定性,當(dāng)程序希望從弱引用中取出被引用對(duì)象時(shí),可能這個(gè)被引用對(duì)象已經(jīng)被釋放了。如果程序需要使用被引用的對(duì)象,則必須重新創(chuàng)建該對(duì)象。
(4)虛引用
軟引用和弱引用可以單獨(dú)使用,但虛引用不能單獨(dú)使用,單獨(dú)使用虛引用沒(méi)有太大的意義。虛引用的主要作用就是跟蹤對(duì)象被垃圾回收的狀態(tài),程序可以通過(guò)檢查虛引用關(guān)聯(lián)的引用隊(duì)列中是否包含指定的虛引用,從而了解虛引用所引用的對(duì)象是否將被回收.
引用隊(duì)列由java.lang.ref.ReferenceQueue類(lèi)表示,它用于保存被回收對(duì)象的引用。當(dāng)把軟引用,弱引用和引用隊(duì)列聯(lián)合使用時(shí),系統(tǒng)回收被引用的對(duì)象之后,將會(huì)把被回收對(duì)象對(duì)應(yīng)的引用添加到關(guān)聯(lián)的引用隊(duì)列中。與軟引用和弱引用不同的是,虛引用在對(duì)象被釋放之前,將把它對(duì)應(yīng)的虛引用添加到關(guān)聯(lián)的隊(duì)列中,這使得可以在對(duì)象被回收之前采取行動(dòng)。
虛引用通過(guò)PhantomReference類(lèi)實(shí)現(xiàn),它完全類(lèi)似于沒(méi)有引用。虛引用對(duì)對(duì)象本身沒(méi)有大的影響,對(duì)象甚至感覺(jué)不到虛引用的存在。如果一個(gè)對(duì)象只有一個(gè)虛引用,那它和沒(méi)有引用的效果大致相同。虛引用主要用于跟蹤對(duì)象被垃圾回收的狀態(tài),虛引用不能單獨(dú)使用,虛引用必須和隊(duì)列ReferenceQueue聯(lián)合使用.
posted on 2013-11-15 11:12 順其自然EVO 閱讀(202) 評(píng)論(0) 編輯 收藏