众所周知,在Java中不需要程序员去主动管理内存,由JVM去负责内存的回收和分配。这样一来简化了程序员的工作,但是呢这也带来一个问题,就是不够灵活,垃圾回收对于程序员来说是不可控的。
在JDK1.2以前,如果一个对象不被任何变量引用,则程序无法再次使用这个对象,这个对象最终会被GC(GabageCollection:垃圾回收)。但是如果之后可能还会用到这个对象,就只能去新建一个了,这其实就降低了JVM性能,没有达到最大的优化策略。
因此,从JDK1.2开始,提供了四种类型的引用:强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。主要有两个目的:
- 可以在代码中决定某些对象的生命周期;
- 优化JVM的垃圾回收机制。
四种引用类型
强引用
强引用是最普遍的引用,如果一个对象具有强引用,那么即使内存不足(JVM抛出OutOfMemoryError),该对象也不会被回收。
1 | // obj就是一个强引用 |
软引用
如果一个对象只具有软引用,当内存空间足够的时候,它就不会被回收,只有当内存不足的时候,
软引用才会被回收。JVM会优先回收长时间闲置不用的软引用的对象,对那些刚刚构建的或刚刚使用过的“新”软引用对象会尽可能保留。软引用可以和引用队列配合使用,如果一个对象即将被垃圾回收了,那么该软引用将会被添加到引用队列里。
1 |
|
弱引用
持有弱引用的对象只能存活到下一次垃圾回收发生之前,无论内存空间是否足够,弱引用都会被回收。不过由于垃圾收集线程是一个优先级很低的线程,可能弱引用无法被及时回收。
1 | Object obj = new Object(); |
虚引用
与其它三种引用不同的是,虚引用不会决定对象的生命周期,如果一个对象持有虚引用,那么它就等于和没有任何引用一样,无法通过虚引用获取到该对象,在任何时候都可能被垃圾回收。虚引用主要作用是跟踪对象被垃圾回收的活动。虚引用必须和引用队列联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
1 | Object obj = new Object(); |
我们可以通过判断引用队列中是 否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取相应的措施。
参考
- Java中的四种引用类型
- 深入理解Java虚拟机