1. 程式人生 > >【JAVA】談談記憶體洩露

【JAVA】談談記憶體洩露

                                               談談記憶體洩露

應屆生面試中,常常被問到記憶體洩露,比方說什麼是記憶體洩露呀?造成記憶體洩露的情況等等。本菜今天就總結一下記憶體洩露方面的幾點小知識。

一、什麼是記憶體洩露

不再被使用的物件持續佔據記憶體,造成記憶體浪費的情形稱作記憶體洩露。這些物件被某些變數引用著,因此垃圾回收器無法回收它們。關於垃圾回收器如何判斷物件的存活狀態,請移步我的另外一篇文章

【JAVA】如何判斷物件已經死亡?

當然引用型別也會對物件的生命週期造成影響,我的另外一篇文章【JAVA】java中的四種引用


二、造成記憶體洩露的情形及對應解決方案

【1】長生命週期的物件持有短生命週期物件的引用,就很有可能造成記憶體洩露。 

長生命週期的物件往往和整個程式的生命週期相同,若是當它們持有短生命週期的物件的引用,儘管短物件不再被使用,也無法被垃圾回收器回收,因為垃圾回收器無法回收被強引用所關聯的物件。

解決方案:

(1)像一些靜態的集合類,它們的生命週期和整個程式相同,儘管放入集合中的元素不再需要,就算將元素強行置為null,但由於集合類持有它們的引用,這些元素佔據的空間也得不到釋放,那麼在必要的時候,我們可以將集合類物件型別的變數置為null。

(2)單例模式中,單例與整個程式的生命週期一致,如果單例物件持有其他短物件的引用,也很容易造成記憶體洩露,這還得靠我們謹慎編碼。

(3)又或是資料庫連線物件(長生命週期),ResultSet與Statement物件(短生命週期),連線不再被使用時,需要呼叫其close()方法,釋放長物件與短物件。同理,需要顯式呼叫close()方法的長生命週期的物件還有Socket、IO流、Session等。


【2】非靜態的外部類會隱式地持有外部類的一個強引用。

在Android中,如果在Activity內宣告一個非靜態的內部類,那麼只要該內部類沒有被回收的話,那麼外部類Activity就無法被回收,Activity所關聯的檢視和資源也不會被回收,這樣的記憶體洩露比較嚴重。

解決方案:

(1)將非靜態內部類改為靜態內部類,靜態內部類屬於類,因此不會依賴與外部類的例項,從而不持有外部類例項的引用。

(2)顯式地宣告非靜態內部類持有外部類的一個弱引用,被弱引用關聯的物件,在下一次垃圾回收器活動時,就會被回收。