java垃圾回收機制的工作特征解析

時間:2022-03-30 03:38:00

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

java垃圾回收機制的工作特征解析

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

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

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

一、垃圾回收及其意義

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

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

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

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

二、垃圾的判斷標準與回收方法

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

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

integeri=newinteger(0);

...

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

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

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

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

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

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

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

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

if(inputstream!=null)

{

inputstream.invalidate();

inputstream=null;

}

在對性能要求比較高的項目中,如果一個對象用完后要將其引用變量指向null。

三、java垃圾收集工作的的特點

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

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

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

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

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

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

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

結(jié)束語:

對于java的垃圾回收工作,在寫程序時要考慮以下準則:

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

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

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

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

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