陸立松
克拉瑪依職業(yè)技術(shù)學(xué)院,新疆 克拉瑪依 833600
JAVA中的內(nèi)存泄漏是指存在一些被分配的對象,它們有兩個特點:其一,這些對象在有向圖中可以與存在通路相連,即可達(dá)性;其二,程序在后續(xù)不會再使用這些對象,即無用性。假如被分配的對象同時滿足這兩個條件,即可判定其為JAVA中的內(nèi)存泄漏,GC不會將其進(jìn)行回收,因此它們占用內(nèi)存。
最常見的是引用廢棄聚集,當(dāng)對象加入一個聚集時就不再被需要,但是未沒有被移除,特別是此聚集用St atic聲明,并存在于程序的整個生命周期時,該問題尤其突出;此外還有一種由于引用臨時對象而產(chǎn)生的錯誤,臨時對象經(jīng)過使用就會變成垃圾,如果仍保持引用,GC就無法回收這些失效對象,從而產(chǎn)生內(nèi)存泄漏。要解決這類問題,可以采用以下幾種方法:如果引用了失效對象要及時清除;盡可能少用靜態(tài)集合和臨時對象;對象如果不用盡量設(shè)置為Null等。
幾乎所有的大型應(yīng)用程序都會有不同形式的全局?jǐn)?shù)據(jù)庫,而在FAVA中全局變量無法在所有類這之外進(jìn)行定義,其全局變量只可以利用在一個類中對靜態(tài)、公用的變量進(jìn)行定義的方法來實現(xiàn),而靜態(tài)變量會永駐內(nèi)存,因此導(dǎo)致內(nèi)存泄漏的問題在所難免??梢岳们宄鳂I(yè)解決該問題,這個作業(yè)為周期運行,可以驗證數(shù)據(jù)中的數(shù)據(jù),將無用的數(shù)據(jù)清除。此外還可以通過引用記數(shù)的方法來解決,集合的主要對集合中每個元素的引用者數(shù)量進(jìn)行統(tǒng)計,引用者將不再引用元素的通知發(fā)送給集合;假如引用者數(shù)量為零,集合中的該元素就可以進(jìn)行移除。
通常系統(tǒng)處于正常運行的情況下,其內(nèi)存占用量通常是穩(wěn)定的,而不應(yīng)出現(xiàn)無限增長的問題;與此對應(yīng)的,任何一個類的對象使用個數(shù)也同樣有一個上限,也不能無限增長。按照這種假設(shè)可以對系統(tǒng)在運行過程序所使用的內(nèi)存大小及實例個數(shù)進(jìn)行持續(xù)觀察:假如內(nèi)存大小不斷增長,或者特定類的實例對象數(shù)量隨著時間不斷增長,那么該系統(tǒng)就有存在內(nèi)存泄漏的可能。還有一種方法可以判斷是否出現(xiàn)內(nèi)存泄漏:如果應(yīng)用程序中出現(xiàn)Out Of Memory Error,系統(tǒng)也有發(fā)生內(nèi)存泄漏的可能,當(dāng)然不能排除應(yīng)用程序正在使用的內(nèi)存量確實是這么多,但是多數(shù)情況下出現(xiàn)Out Of Memory Error均有可能出現(xiàn)了內(nèi)存泄漏。此外,還可以對GC的活動進(jìn)行持續(xù)的監(jiān)控,如果隨著時間的增加系統(tǒng)內(nèi)存使用量也不斷上升,那就有發(fā)生內(nèi)存泄漏的可能。
當(dāng)檢測到確實出現(xiàn)了內(nèi)存泄漏,進(jìn)行處理時就要利用專業(yè)工具,這些工具采用字節(jié)碼技術(shù)及JVMTI等方法由JVM獲取內(nèi)存系統(tǒng)信息。其中JVMTI為標(biāo)準(zhǔn)接口,其前身是JVMPI,其作為外部工具與JVM通信,搜集JVM的信息;而字節(jié)碼儀器所引用的是預(yù)處理技術(shù),該技術(shù)利用探針獲取工具所需要的字節(jié)信息。不過目前多數(shù)處理內(nèi)存泄漏的工具均是基于JVMTI進(jìn)行的,JVMTI會使系統(tǒng)的內(nèi)存增加,執(zhí)行程序的速度變慢。而另外一種工具JRockit Memory Leak Detector是基于BEAJVM運行的,它內(nèi)嵌于BEAJ Rockit JVM,系統(tǒng)全速運行時也可以使用,而且不會出現(xiàn)其它與此類工具相關(guān)聯(lián)的性能開銷,所以不存在上述缺點。應(yīng)用JRockit Memory Leak Detector處理內(nèi)存泄漏可以經(jīng)由以下幾個步驟來實現(xiàn):
首先借助趨勢分析找出存在泄漏的對象類,JRockit Memory Leak Detector所提供的趨勢分析功能可以描述應(yīng)用程序中各類使用堆空間的情形,可以通過它了解某一類型實例所占用空間的大小,或者占用了堆的哪一部分,存在實例的數(shù)量和堆空間使用的每秒增加速度,其中增長過快的對象就值得懷疑。其次,尋找與泄漏對象相關(guān)的其它類,通過對趨勢分析表的分析選擇一個可疑類型,所有具有指向選中類型的實例的類型均可以在一個圖中顯示出來,用戶就能夠回溯到造成引用的根本原因。類的實例能夠被顯示、內(nèi)觀,指向一個選中實例的所有實例均能夠顯示于一張實例圖,可以通過分配跟蹤對某個類的分配情況進(jìn)行跟蹤。最后再向下發(fā)掘,找出獨立的對象間互相聯(lián)系的方式。此外,該工具還可以動態(tài)的尋找所有內(nèi)存分配的堆棧路徑,同時通過上述3種特性,可以把該工具集成在JVM中,從而對內(nèi)存泄漏進(jìn)行安全有效的捕捉與修復(fù)。
在實際應(yīng)用過程中,如果可以結(jié)合GC的運行機制,在進(jìn)行設(shè)計與編碼時更具針對性,從而有效的減少或者消除內(nèi)存泄漏。具體的措施如下:第一,盡量少用靜態(tài)對象變量或者靜態(tài)集合類,因為被靜態(tài)集合類引用的對象無法被GC回收,易導(dǎo)致內(nèi)存泄漏;第二,使用內(nèi)部類要謹(jǐn)慎,因為內(nèi)部類中往往隱藏有外部類對象實例的引用,如果未得到釋放會造成整個系列對象無法釋放;第三,不可采用生命周期長的對象去管理生命周期短的對象;第四,物理連接要及時關(guān)閉;第五,釋放資源或者清除引用時要調(diào)用對象的特定方法;第六,清除本地的系統(tǒng)資源時可以采用Finalize方法。
[1]馮濤,宋成明.清剿Java程序中的內(nèi)存泄漏[J].計算機技術(shù)與發(fā)展,2008(4).
[2]賈曉霞,吳際,金茂忠,等.Java程序內(nèi)存泄漏綜述[J].計算機應(yīng)用研究,2009(6).
[3]黃山,楊全勝,杜中軍,等.Java內(nèi)存管理和內(nèi)存泄漏的研究[J].中國民航飛行學(xué)院學(xué)報,2009(5).
[4]陳華.探討JAVA的內(nèi)存泄漏問題[J].IT技術(shù)論壇,2008(33).