background image

17

     }

18

 }

    在这段代码中,FileSearch 类中有一个函数 hasString,用来判断文档中是否含有指
定的字符串。流程是先将 mFile 加载到内存中,然后进行判断。但是,这里的问题是,将
content 声明为了实例变量,而不是本地变量。于是,在此函数返回之后,内存中仍然存
在整个文件的数据。而很明显,这些数据我们后续是不再需要的,这就造成了内存的无故
浪费。
    要避免这种情况下的内存泄露,要求我们以 C/C++的内存管理思维来管理自己分配
的内存。第一,是在声明对象引用之前,明确内存对象的有效作用域。在一个函数内有效
的内存对象,应该声明为 local 变量,

与类实例生命周期相同的要声明为实例变量

……以

此类推。第二,在内存对象不再需要时,记得手动将其引用置空。

复杂数据结构中的内存泄露问题

    在实际的项目中,我们经常用到一些较为复杂的数据结构用于缓存程序运行过程中需
要的数据信息。有时,由于数据结构过于复杂,或者我们存在一些特殊的需求(例如,在
内存允许的情况下,尽可能多的缓存信息来提高程序的运行速度等情况),我们很难对
数据结构中数据的生命周期作出明确的界定。这个时候,我们可以使用 Java 中一种特殊
的机制来达到防止内存泄露的目的。
    之前我们介绍过,Java 的 GC 机制是建立在跟踪内存的引用机制上的。而在此之前,

我们所使用的引用都只是定义一个 Object o;”这样形式的。事实上,这只是 Java 引用机
制中的一种默认情况,除此之外,还有其他的一些引用方式。通过使用这些特殊的引用机
制,配合 GC 机制,就可以达到一些我们需要的效果。

Java 中的几种引用方式

    Java 中有几种不同的引用方式,它们分别是:强引用、软引用、弱引用和虚引用。下面,
我们首先详细地了解下这几种引用方式的意义。
    
      强引用

在此之前我们介绍的内容中所使用的引用都是强引用,这是使用最普遍的引用。如果

一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内
存空 间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不
会靠随意回收具有强引用的对象来解决内存不足问题。

软引用(SoftReference)
SoftReference 类的一个典型用途就是用于内存敏感的高速缓存。SoftReference 

的原理是:在保持对对象的引用时保证在 JVM 报告内存不足情况之前将清除所有的软引
用。关键之处在于,垃圾收集器在运行时可能会(也可能不会)释放软可及对象。对象是
否被释放取决于垃圾收集器的算法 以及垃圾收集器运行时可用的内存数量。

弱引用(WeakReference)
WeakReference 类的一个典型用途就是规范化映射(canonicalized mapping)。

另外,对于那些生存期相对较长而且重新创建的开销也不高的对象来说,弱引用也比较