Java中的引用主要有以下几种类型:
• 强引用(StrongReference):强引用是使用最普遍的引用。只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

• 软引用(SoftReference):软引用是用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,内存空间足够,垃圾回收器就不会回收它,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

• 弱引用(WeakReference):弱引用也是用来描述非必需对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

• 虚引用(PhantomReference):“虚引用”顾名思义,就是形同虚设,也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。


下面主要来谈谈软引用。
对于软引用对象本身,至少有两个强引用指向它:由应用创建的原始的强引用,还有就是JVM创建的在所引对象队列上的一个新的强引用。软引用本质上是一个比较大的、最近最久未用的对象池。获得较好性能的关键是确保它们会被及时清理。

不要使用太多软引用,它们很容易填满整个堆。

当问题中的所引对象会同时被几个线程使用时,应该考虑弱引用。否则,弱引用很可能会被垃圾收集器回收:只有弱引用的对象在每个GC周期都可以回收。当强引用被移除时,弱引用会立即释放。

软:只要有足够内存,而且看上去有人会偶尔访问它,就留着它。
弱:只要有其他人对这个对象感兴趣就让我知道它在哪,但是如果他们不再需要它了,就丢了,我自己会重新创建。

软引用的对象通常可以存活几分钟甚至几小时,但是只要所引读写仍然存在,弱引用对象就会一直存活(下一个GC周期会清理)。

在Java中,集合类经常是内存泄露的根源。比如某个应用将对象放入一个HashMap对象中,但从不移除。随着时间推移,这个HashMap对象会越来越大,而且消耗堆。