1. 程式人生 > >詳解java記憶體洩露和如何避免記憶體洩漏

詳解java記憶體洩露和如何避免記憶體洩漏

源地址:http://www.xttblog.com/?p=518

一直以來java都佔據著語言排行榜的頭把交椅。這是與java的設計密不可分的,其中最令大家喜歡的不是面向物件,而是垃圾回收機制。你只需要簡單的建立物件而不需要負責釋放空間,因為Java的垃圾回收器會負責記憶體的回收。然而,情況並不是這樣簡單,記憶體洩露還是經常會在Java應用程式中出現。
下面我們將詳細的學習什麼是記憶體洩露,為什麼會發生,以及怎樣阻止記憶體洩露。

什麼是記憶體洩露

記憶體洩露的定義:對於應用程式來說,當物件已經不再被使用,但是Java的垃圾回收器不能回收它們的時候,就產生了記憶體洩露。
要理解這個定義,我們需要理解物件在記憶體中的狀態。如下圖所示,展示了哪些物件是無用物件,哪些是未被引用的物件;
java記憶體中的狀態


上圖中包含了未引用物件和引用物件。未引用物件將會被垃圾回收器回收,而引用物件卻不會。未引用物件很顯然是無用的物件。然而,無用的物件並不都是未引用物件,有一些無用物件也有可能是引用物件,這部分物件正是記憶體洩露的來源。
java物件相互引用

為什麼記憶體洩露會發生

讓我們用下面的例子來看看為什麼會發生記憶體洩露。如下圖所示,物件A引用物件B,A的生命週期(t1-t4)比B的生命週期(t2-t3)要長,當B在程式中不再被使用的時候,A仍然引用著B。在這種情況下,垃圾回收器是不會回收B物件的,這就可能造成了記憶體不足問題,因為A可能不止引用著B物件,還可能引用其它生命週期比A短的物件,這就造成了大量無用物件不能被回收,且佔據了昂貴的記憶體資源。
同樣的,B物件也可能引用著一大堆物件,這些被B物件引用著的物件也不能被垃圾回收器回收,所有的這些無用物件消耗了大量記憶體資源。

怎樣阻止記憶體洩露

1.使用List、Map等集合時,在使用完成後賦值為null
2.使用大物件時,在用完後賦值為null
3.目前已知的jdk1.6的substring()方法會導致記憶體洩露
4.避免一些死迴圈等重複建立或對集合新增元素,撐爆記憶體
5.簡潔資料結構、少用靜態集合等
6.及時的關閉開啟的檔案,socket控制代碼等
7.多關注事件監聽(listeners)和回撥(callbacks),比如註冊了一個listener,當它不再被使用的時候,忘了登出該listener,可能就會產生記憶體洩露