Java一个最重要的特性就是内存的管理。你只需简单的创建对象,Java的内存垃圾收集器会负责内存的分配与回收。然而,情况不是简单是这样,因为在一些Java应用当中
经常有内存泄露现象。
本文会介绍什么是内存泄露,为什么会发生以及如何防止其发生。
一、什么是内存泄露
内存泄露的定义:对象不再被应用使用,然而垃圾收集器无法移出它们,因为它们仍在被引用。
为了能理解这个定义,我们需要理解对象在内存中的状态。以下图描述了什么是不再使用和不再被引用。
从图能看出,对象有被引用的与不在被引用的状态。不在被引用的对象将会被垃圾回收掉,而处于引用状态的对象则不会。不在被引用的对象百分比属于不使用的状态,
因为没有其他对象引用它。但不在使用状态的对象并不是全部都处于不在被引用状态。它们中的部分对象处于引用状态当中!内存泄露正来源于此。
二、为什么出现内存泄露
通过一下的例子来说明为什么会内存泄露。在以下例子中,A 对象引用了B对象。A 对象的存活时间(t1 ——t4)比B对象的存活时间(t2——t3)长很多。当B对象在应用中不在
被使用的时候,A对象仍然持有对B对象的引用。在这样的情况下,垃圾收集器无法将B对象从内存中移除。这样将可能导致内存溢出的问题,因为假设在A对象为很多的对象做
同样操作的情况下,从而此处将会有大量未被收集的对象继续消耗内存。
还有一种可能情况是B对象持有一堆其他对象的引用。这些对象因被B对象引用所以也无法被收集。所有这些未被使用的对象都将消耗以上的内存空间。
三、如何防止内存泄露
以下是一些防止内存泄露可快速亲手实践的技巧。
1、注意集合类,比如 HashMap,ArrayList等等,是发现内存泄露的普遍的地方。当它们声明为static时,它们的存活时间与应用一样。
2、注意监听类(listeners) 和回调(callback)。如果一个类注册了一个监听但没有注销这个监听当这个类不再使用时,就可能出现泄露。
3、“如果一个类自己管理自己的内存,程序员应该警惕内存泄露" [1]通常情况下一个对象指向其他对象的成员变量需要置空(设置为null)
参考:
[1] Bloch, Joshua. Effective java. Addison-Wesley Professional, 2008.