天天看点

关于强引用、软引用、弱引用与虚引用的一些知识

关于强引用、软引用、弱引用与虚引用的一些知识

在Java中,除基本数据类型外,剩余的都是指向各类对象的对象引用,因而按照其生命周期的长短,可进行引用分类。不同的引用类型主要体现的是对象不同的可达性状态和对垃圾收集的影响。

1、强引用

  • 使用 new 创建的对象关联的引用皆为强引用。
  • JVM出现内存不足时,即使抛出OOM异常终止程序也不会轻易回收具有强引用的对象来释放内存。
  • 对于普通的对象,如果没有其它的引用关系,只要超过了引用的作用域或显式将其对应引用赋值为 null ,就可被垃圾回收器回收,具体回收时机由GC策略决定。

2、软引用

  • 通过 SoftReference 类实现。
  • 生命周期短于强引用,当JVM认为内存不足时会去试图回收软引用指向的对象,以避免抛出OOM异常。
  • 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被GC回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续可以调用 ReferenceQueue 的 poll() 方法来检查是由有它关心的对象被回收。如果队列为空,则返回null,否则返回队列中前面的一个 Reference 对象。
  • 软引用适用于作为内存敏感的缓存,若内存有空闲,则暂时保留缓存,当内存不足时则会被清理以保证内存不被耗尽。

3、弱引用

  • 通过 WeakReference 类实现。
  • 弱引用生命周期比软引用短,当垃圾回收器线程扫描其负责的内存区域时,一旦发现具有弱引用的对象,就会立即对其进行回收,而不管当前内存是否充足与否。但由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。
  • 弱引用可与引用队列(ReferenceQueue)联合使用,如果弱引用被回收,Java虚拟机就会把这个弱引用加入相关联的引用队列中。
  • 适用内存敏感的缓存。

4、虚引用(幻象引用)

  • 通过 PhantomReference 类实现。
  • 我们无法通过虚引用访问对象的任何属性或函数。虚引用仅提供一种在对象被finalize之后能做某些事情的机制。
  • 若一个对象仅持有虚引用则跟没有持有任何引用引用,随时能被垃圾回收器回收。
  • 虚引用必须和引用队列联合使用,当GC准备回收一个对象时,若发现其还持有虚引用,则会在回收对象的内存之前,将这个虚引用加入到与之关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
           
  • 程序可通过判断引用队列中是否以及加入了虚引用,来了解被引用的对象是否将被垃圾回收。若程序发现某个虚引用以及被加入到引用队列,就可以在所引用的对象的内存被回收之前采取一些操作。
  • 虚引用适用于跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾回收器回收之前会收到通知。