Java提升篇—— 簡單介紹Java 的內存泄漏

  java最明顯的一個優點就是它的內存管理機制。你只需簡單建立對象,java的垃圾回收機制負責分配和釋放內存。然而狀況並不像想像的那麼簡單,由於在Java應用中常常發生內存泄漏。java

本教程演示了什麼是內存泄漏,爲何會發生內存泄漏以及如何預防內存泄漏。程序員

什麼是內存泄漏?

定義:若是對象在應用中再也不被使用,但因爲它們在其餘地方被引用,垃圾回收卻不能移除它們(這樣就形成了不少內存不能釋放,從而致使內存溢出的現象。譯註)。對象

要理解這必定義,咱們須要理解內存中對象的狀態。下圖說明了那些是未使用,那些是未引用。blog

where-is-memory-leak

從圖中能夠看到被引用對象和未引用對象(的範圍)。未引用對象能夠被垃圾回收機制回收,而被引用對象不能被垃圾回收機制回收。未引用對象固然是沒有使用的,由於沒有其餘對象引用了它。然而未使用對象並不都是未引用的。某些未使用的對象仍然被其餘地方引用!這就是內存泄漏原由。教程

爲何會發生內存泄漏?

讓咱們來下面的這個例子,看看爲何會發生內存泄漏。在以下例子中,A對象引用了B對象。A的生命週期(t1-t4)比B的生命週期(t2-t3)要長的多,當B再也不在應用中被使用,A仍然持有對B的引用。這樣一來,垃圾回收機制不能從內存中移除B。這頗有可能致使內存溢出問題,由於若是其餘不少對象像A同樣,那麼內存中將會有不少不能被回收的對象,這將消耗大量內存空間。生命週期

也有可能的狀況是B持有了大量對其餘對象的引用。這些被B引用的對象一樣不會被回收掉。全部這些未使用的對象將會消耗寶貴的內存空間。 事件

如何預防內存泄漏?

以下是一些預防內存泄漏的快速技巧:內存

一、留意集合類,好比HashMap,ArrayList等等,由於他們是內存泄漏常常發生的地方。當它們被聲明爲靜態對象時,他們的生命週期就和應用的生命週期同樣長。get

二、留意事件監聽器和回調。若是一個類註冊了監聽器,但當該類再也不被使用後沒有註銷監聽器,可能會發生內存泄漏。源碼

三、「若是一個類管理本身的內存,程序員應該警戒內存泄漏。」[1],不少時候對象中的指向其餘對象成員變量須要設置成null(才能被回收)。

一個小測驗:爲何JDK6中的substring()方法會引起內存泄漏?

要回答這個問題,你可能須要查看JDK6和7中substring()的源碼。

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

相關文章
相關標籤/搜索