簡述Java內存泄露

翻譯人員: 鐵錨
翻譯時間: 2013年11月4日
原文連接: The Introduction of Memory Leaks

內存管理一直是Java 所鼓吹的強大優勢。開發者只須要簡單地建立對象,而Java的垃圾收集器將會自動管理內存空間的分配和釋放.但在不少狀況下,事情並不那麼簡單,在 Java程序中老是會頻繁地發生內存泄露(Memory Leaks).
本文闡述什麼是內存泄露,爲何會泄露,以及如何防止內存泄露。

內存泄露是什麼?
內存泄露的定義: 當某些對象再也不被應用程序所使用,可是因爲仍然被引用而致使垃圾收集器不能釋放(Remove,移除)他們.
用白話來講就是: 該回收的內存沒被回收,最後由於內存不夠用而致使程序報錯。

要理解這個定義,咱們須要理解內存中的對象狀態. 下圖展現了什麼是不使用的部分,以及未被引用的部分。


圖1

從圖中能夠看出,內存中存在着 有引用的對象,和無引用的對象. 無引用的對象將被垃圾收集器所回收,而有引用的對象則不會被當作垃圾收集. 由於沒有任何其餘對象所引用,因此無引用對象必定是再也不使用的。 可是有一部分無用對象仍然被(無心中)引用着。這就是發生內存泄露的根源.

爲何內存會泄露?
讓咱們看下面的實例來了解爲何內存會泄露. 在下面的情境中,對象A引用了對象B. A的生命週期(t1 - t4) 比 B的(t2 - t3)要長得多. 當對象B在應用程序邏輯中不會再被使用之後, 對象 A 仍然持有着 B的引用. (根據虛擬機規範)在這種狀況下垃圾收集器不能將 B 從內存中釋放. 這種狀況極可能會引發內存問題,倘若A 還持有着其餘對象的引用,那麼這些被引用的(無用)對象都不會被回收,並佔用着內存空間.
甚至有可能 B 也持有一大堆其餘對象的引用。 這些對象因爲被 B 所引用,也不會被垃圾收集器所回收. 全部這些無用的對象將消耗大量寶貴的內存空間。

圖2

怎麼防止內存泄露?
要防止內存泄露,下面是一些快速上手的實用技巧:
1. 小心集合類,好比 HashMap,ArrayList等,由於這是最容易發生內存泄露的地方.當集合對象被聲明爲static時,他們的生命週期通常和整個應用程序同樣長。
2. 注意事件監聽和回調.當註冊的監聽器再也不使用之後,若是沒有被註銷,那麼極可能會發生內存泄露.
3. "當一個類本身管理其內存空間時,程序員應該注意內存泄露." 經常是一個對象的成員變量須要被置爲null 時仍然指向其餘對象,

一個小測驗: 爲何 JDK6 中的 substring() 方法有可能致使內存泄露?
要回答這個問題,請參考:  JDK6和JDK7中String的substring()方法及其差別

參考資料:
[1] Bloch, Joshua. Effective java. Addison-Wesley Professional, 2008.
[2] IBM Developer Work. http://www.ibm.com/developerworks/library/j-leaks/

相關文章:
1.  

Java 對象在堆中的內存結構


2.   Java 數組在內存中的結構
3. How is an array stored in memory and brought to cache?
4.  Java String 常見問題
相關文章
相關標籤/搜索