垃圾收集幾乎是每個開發人員都喜愛的一個Java平台特性,它簡化了開發,消除了所有種類的潛在代碼錯誤。可儘管垃圾收集一般來說可以讓您無需進行資源管理,有時候您還是必須自己進行一些內務處理。在本文中,BrianGoetz討論了垃圾收集的局限性,並指出了您必須自己做內務處理的場景。
小時候,父母總是叮囑我們玩了玩具之後要收好。如果您仔細想想,其實這種嘮叨並不過分,要保持整潔是因為存在實際的限制,房間裡沒有太多的空間,如果到處堆滿了玩具,那么連走路都無處下腳了。
如果有了足夠的空間,保持整潔就不是那么必要了。空間越多,就越不必要保持整潔。ArloGuthrie著名的民謠Alice'sRestaurantMassacre說明了這一點:
他們住在教堂樓下的大廳,裡面的椅子全都搬走了,剩下一個空蕩蕩的大房間,所以他們想,很長時間都不用把垃圾扔出去,有的是地方裝垃圾……
無論如何,垃圾收集可以幫我們減輕內務整理方面的工作。
顯式地釋放資源
Java程式中使用的絕大多數資源都是對象,垃圾收集在清理對象方面做得很好。因此,您可以使用任意多的String。垃圾收集器最終無需您的干預就會算出它們何時失效,並收回它們使用的記憶體。
另一方面,像檔案句柄和套接字句柄這類非記憶體資源必須由程式顯式地釋放,比如使用close()、destroy()、shutdown()或release()這樣的方法來釋放。有些類,比如平台類庫中的檔案句柄流實現,提供終結器(Finalizer)作為安全保證,以便當垃圾收集器確定程式不再使用資源而程式卻忘了釋放資源時,終結器還可以來做這個釋放工作。但是儘管檔案句柄提供了終結器來在您忘記了時為您釋放資源,最好還是在使用完之後顯式地釋放資源。這樣做可以更早地釋放資源,降低了資源耗盡的可能。
對於有些資源來說,一直等到終結(finalization)釋放它們是不可取的。對於重要的資源,比如鎖獲取和信號量許可證,Lock或Semaphore直到很晚都可能不會被垃圾收集掉。對於資料庫連線這樣的資源,如果您等待終結,那么肯定會消耗完資源。許多資料庫伺服器根據許可的容量,只接受一定數量的連線。如果伺服器應用程式為每個請求都打開一個新的資料庫連線,然後用完之後就不管了,那么資料庫遠遠未到終結器關閉不再需要的連線,就會到達它的最高容量。
只限於一個方法的資源
多數資源都不會持續整個應用程式的生命周期,相反,它們只被用於一個活動的生命周期。當應用程式打開一個檔案句柄讀取檔案以處理文檔時,它通常讀取檔案後就不再需要檔案句柄了。