java垃圾回收機(jī)制的工作特征解析

時(shí)間:2022-03-30 03:38:00

導(dǎo)語(yǔ):java垃圾回收機(jī)制的工作特征解析一文來源于網(wǎng)友上傳,不代表本站觀點(diǎn),若需要原創(chuàng)文章可咨詢客服老師,歡迎參考。

java垃圾回收機(jī)制的工作特征解析

關(guān)鍵詞:java虛擬機(jī);垃圾收集;垃圾收集器

摘要:垃圾收集是java語(yǔ)言區(qū)別于其他程序設(shè)計(jì)語(yǔ)言的一大特色。但是目前多數(shù)的java書籍有關(guān)垃圾收集的內(nèi)容幾乎沒有或只做了非常簡(jiǎn)單的介紹。本文從多個(gè)方面分析了java的垃圾回收機(jī)制,使學(xué)習(xí)者能夠?qū)υ摍C(jī)制產(chǎn)生一個(gè)全面的認(rèn)識(shí)。

java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例從中分配空間,堆中存儲(chǔ)著正在運(yùn)行的應(yīng)用程序建立的所有對(duì)象。垃圾回收是一種動(dòng)態(tài)存儲(chǔ)管理技術(shù),它自動(dòng)釋放不再被程序引用的對(duì)象,按照特定的垃圾收集算法來實(shí)現(xiàn)資源的自動(dòng)回收。一般來說,堆的回收是由垃圾收集器負(fù)責(zé)的,盡管jvm規(guī)范并不要求特殊的垃圾回收技術(shù),但是由于內(nèi)存的有限性,jvm在實(shí)現(xiàn)的時(shí)候都有一個(gè)由垃圾回收所管理的堆。

一、垃圾回收及其意義

正在運(yùn)行的程序中被引用的對(duì)象處于存活狀態(tài),不再被引用的對(duì)象就是通常所說的垃圾,查找并釋放垃圾對(duì)象所占用內(nèi)存空間的過程稱為垃圾收集。

在java中,當(dāng)沒有對(duì)象引用指向分配給某個(gè)對(duì)象的內(nèi)存時(shí),該內(nèi)存便成為垃圾。jvm的一個(gè)系統(tǒng)級(jí)線程會(huì)自動(dòng)釋放該內(nèi)存。除了釋放沒有用的對(duì)象,垃圾收集也可以清除內(nèi)存記錄碎片。由于創(chuàng)建對(duì)象和釋放對(duì)象所占的內(nèi)存空間,內(nèi)存會(huì)出現(xiàn)碎片。碎片整理將所占用的堆內(nèi)存移到堆的一端,將整理出的內(nèi)存分配給新的對(duì)象。

垃圾收集機(jī)制有如下優(yōu)點(diǎn):首先,它能使編程效率提高。在沒有垃圾收集機(jī)制的時(shí)候,可能要花許多時(shí)間來解決一個(gè)難懂的存儲(chǔ)器問題,而使用java的垃圾收集機(jī)制可大大節(jié)省時(shí)間。其次,它能避免內(nèi)存滲漏體的產(chǎn)生,保護(hù)程序的完整性,垃圾收集是java語(yǔ)言安全性策略的一個(gè)重要組成部分。

垃圾收集的一個(gè)潛在的缺點(diǎn)是它的開銷影響程序性能。java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對(duì)象,并且釋放沒用的對(duì)象。這一個(gè)過程需要花費(fèi)處理器的時(shí)間。其次垃圾收集算法的不完備性,許多垃圾收集算法不能保證100%收集到所有的廢棄內(nèi)存。

二、垃圾的判斷標(biāo)準(zhǔn)與回收方法

垃圾收集器判斷一個(gè)對(duì)象的內(nèi)存空間是否無(wú)用的標(biāo)準(zhǔn)是:如果該對(duì)象不能再被程序中任何一個(gè)“活動(dòng)的部分”所引用,此時(shí)我們說,該對(duì)象的內(nèi)存空間已經(jīng)無(wú)用。所謂“活動(dòng)的部分”,是指程序中某部分參與程序的調(diào)用,尚未執(zhí)行完畢。

常見的一種情況是,當(dāng)內(nèi)存中的一個(gè)對(duì)象不再被任何變量引用的時(shí)候,這個(gè)對(duì)象就成為內(nèi)存中的垃圾。java的垃圾收集機(jī)制可以發(fā)現(xiàn)這種沒有任何引用的對(duì)象,并在適當(dāng)時(shí)候回收該對(duì)象所使用的內(nèi)存。例如:

integeri=newinteger(0);

...

i=null;//此時(shí),前面integer(0)所產(chǎn)生的對(duì)象就成為垃圾。

具體的說,一個(gè)變量或?qū)ο笫欠窭勺裱缦乱?guī)則進(jìn)行判斷:

(一)變量出了作用域就成為垃圾。

(二)變量名失去指向就會(huì)變成垃圾。

(三)對(duì)象失去變量名的指向同樣變成垃圾。

(四)匿名對(duì)象本身就是垃圾。

垃圾收集在多數(shù)情況下是自動(dòng)進(jìn)行的,也可使用system.gc()方法提醒jvm檢查有沒有要回收的對(duì)象,它不明確的指定jvm去回收哪個(gè)對(duì)象。垃圾收集是jvm上優(yōu)先級(jí)最低的線程,調(diào)用system.gc()在多數(shù)時(shí)候并不馬上進(jìn)行垃圾收集。

項(xiàng)目中最好能手動(dòng)釋放資源,jdk源碼里流的部分的close()方法,其實(shí)底層都是手動(dòng)釋放:

if(inputstream!=null)

{

inputstream.invalidate();

inputstream=null;

}

在對(duì)性能要求比較高的項(xiàng)目中,如果一個(gè)對(duì)象用完后要將其引用變量指向null。

三、java垃圾收集工作的的特點(diǎn)

經(jīng)過前面的分析,可以發(fā)現(xiàn)java的垃圾回收有以下特點(diǎn):

(一)垃圾收集線程作為低優(yōu)先級(jí)的線程運(yùn)行,但在系統(tǒng)可用內(nèi)存量過低的時(shí)候,可能會(huì)突發(fā)地執(zhí)行來釋放內(nèi)存資源。垃圾收集器不可以被強(qiáng)制執(zhí)行,但程序員可以通過調(diào)用system.gc()方法來建議執(zhí)行垃圾收集器。

(二)不能保證一個(gè)無(wú)用的對(duì)象一定會(huì)被垃圾收集器收集,也不能保證垃圾收集器在一段java代碼中一定會(huì)執(zhí)行,因此在程序執(zhí)行過程中被分配出去的內(nèi)存空間可能會(huì)一直保留到該程序執(zhí)行完畢。由此可見,徹底地根絕內(nèi)存滲漏體的產(chǎn)生也是不可能的。

(三)可以通過將對(duì)象的引用變量置為null來通知垃圾收集器來收集該對(duì)象。但如果該對(duì)象連接有事件監(jiān)聽器,那它還是不能被收集。所以在將引用變量置為null之前,應(yīng)首先除去監(jiān)聽器。

(四)每一個(gè)對(duì)象都有一個(gè)finalize()方法,這個(gè)方法是從object類繼承的。finalize()方法用來回收內(nèi)存以外的系統(tǒng)資源,書寫程序時(shí)該方法的順序和方法的實(shí)際調(diào)用順序是不相干的,這是finalize()方法的特點(diǎn)。

java語(yǔ)言允許程序員為任何對(duì)象添加finalize()方法,該方法會(huì)在垃圾收集器回收對(duì)象之前被調(diào)用。但不要過分依賴該方法對(duì)系統(tǒng)資源的回收,因?yàn)樵摲椒ㄕ{(diào)用后的執(zhí)行結(jié)果是不可預(yù)知的。

(五)當(dāng)一個(gè)方法執(zhí)行完畢,其中的局部變量就會(huì)超出使用范圍,此時(shí)可以被當(dāng)作垃圾收集,以后再調(diào)用該方法時(shí),其中的局部變量便會(huì)被重新創(chuàng)建。

結(jié)束語(yǔ):

對(duì)于java的垃圾回收工作,在寫程序時(shí)要考慮以下準(zhǔn)則:

(一)不要試圖去假定垃圾收集發(fā)生的時(shí)間,這一切都是未知的。

(二)java提供了一些用于垃圾收集的類,而且提供了建議進(jìn)行垃圾收集的方法——system.gc(),但這是一個(gè)不確定的方法。java并不保證每次調(diào)用該方法就一定能夠啟動(dòng)垃圾收集。

(三)挑選適合自己的垃圾收集器。如果系統(tǒng)沒有特殊和苛刻的性能要求,可以采用jvm的缺省選項(xiàng)。否則可以考慮使用有針對(duì)性的垃圾收集器,例如增量收集器適合實(shí)時(shí)性要求高的系統(tǒng)。具有較高的配置,有較多閑置資源的系統(tǒng)可以考慮使用并行標(biāo)記/清除收集器。

(四)應(yīng)盡早釋放無(wú)用對(duì)象。引用變量在退出活動(dòng)域后要置為null,通知垃圾收集器來收集該對(duì)象,還要注意引用的對(duì)象是否被監(jiān)聽,如果有,要先去掉監(jiān)聽器。

java開發(fā)人員可以不重視jvm中堆內(nèi)存的分配和垃圾收集,但是充分理解java的這一特性可以讓我們更有效地利用資源。