java最明显的一个优点就是它的内存管理机制。你只需简单建立对象,java的垃圾回收机制负责分配和释放内存。然而状况并不像想像的那么简单,由于在Java应用中常常发生内存泄漏。java
本教程演示了什么是内存泄漏,为何会发生内存泄漏以及如何预防内存泄漏。程序员
定义:若是对象在应用中再也不被使用,但因为它们在其余地方被引用,垃圾回收却不能移除它们(这样就形成了不少内存不能释放,从而致使内存溢出的现象。译注)。对象
要理解这必定义,咱们须要理解内存中对象的状态。下图说明了那些是未使用,那些是未引用。blog
从图中能够看到被引用对象和未引用对象(的范围)。未引用对象能够被垃圾回收机制回收,而被引用对象不能被垃圾回收机制回收。未引用对象固然是没有使用的,由于没有其余对象引用了它。然而未使用对象并不都是未引用的。某些未使用的对象仍然被其余地方引用!这就是内存泄漏原由。教程
让咱们来下面的这个例子,看看为何会发生内存泄漏。在以下例子中,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/