内存泄露(Memory Leaks)简介

来源:互联网 发布:windows 10官方下载 编辑:程序博客网 时间:2024/06/06 08:25

    Java最大的一个优势是它的内存管理。你可以很方便地创建对象,而Java垃圾回收器(Garbage Collector)则会负责分配并释放内存。然而,实际情况并非如此简单,Java应用程序经常会发生内存泄露的问题。

    本文介绍了什么是内存泄露、内存泄露是如何发生的,以及,如何防止内存泄露。

1. 什么是内存泄露?

    内存泄露的定义:应用程序已经不再需要使用对象,但由于它们依然被引用,导致垃圾回收器无法将其移除。

    为了进一步了解这一定义,我们需要知道内存中对象的状态。下图将会说明什么是未被使用(unused),什么是未被引用(unreferenced)。


    上图中,有被引用的对象(referenced object)和未被引用的对象(unreferenced object)。未被引用的对象会被垃圾回收器回收,而被引用的对象则不会。未被引用的对象肯定是未被使用的,因为其他对象没有引用它。然而,未被使用的对象不全是未被引用的。未被使用的对象有可能被引用。这就导致了内存泄露。

2. 为什么会发生内存泄露?

    我们来看看下面的例子,研究内存泄露是如何发生的。在下面的例子中,对象A引用了对象B。A的生命周期(t1-t4)比B的生命周期(t2-t3)长得多。在应用程序中,如果B已经不再被使用,A却还保留着对B的引用。这样,垃圾回收器就无法将B移出内存。一旦A保留了大量对不会再被使用的对象的引用,就会导致大量的对象无法被回收,造成内存空间的消耗,这就很可能出现内存泄露。

    还有可能是,B也保留了大量对其他对象的引用,导致这些被B引用的对象也无法被回收。所有这些未被使用的对象都会消耗宝贵的内存空间。


3. 如何防止内存泄露?

    下面是一些关于内存泄露的实践经验。

    1. 注意集合(Collection)类,如HashMap、ArrayList等,因为使用这些类的地方经常会出现内存泄露。一旦将集合类声明为静态(static),那么它们的生命周期就和应用程序的生命周期一样长。

    2. 注意事件监听器和回调方法。如果事件监听器被注册,当类不再被使用时,要注意将监听器取消注册,否则会出现内存泄露。

    3. “如果类管理它自己的内存,程序员就特别要注意内存泄露的问题。”[1]通常,如果一个对象中的成员变量指向其他的对象,则需要消除这些引用。

4. 小测验:为什么JDK6中的substring()方法会引起内存泄露?

    在文章Substring() in JDK6和7中给出这个问题的答案。


参考文献:

[1] Bloch, Joshua. Effective java. Addison-Wesley Professional, 2008.

[2] IBM Developer Work. http://www.ibm.com/developerworks/library/j-leaks/


原文地址:The Introduction of Memory Leaks

0 0
原创粉丝点击