在JDK1.2 之前, java 中引用的定义:如果引用类型的数据类型中存储的数值代表的是一块内存的起始地址,就称这块内存代表一个引用,在JDK1.2 之后, java 把引用类型分为四种级别,这四种级别由高到低分别是:强引用,软引用,弱引用和虚引用

强引用(StrongReference)

当内存空间不足, Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

因此强引用是造成 Java 内存泄露的主要原因之一。 其实就是我们平时的 String[] arr = new String[]{"a", "b", "c"};

软引用(SoftReference)

  • 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;
  • 如果内存空间不足了,就会回收这些对象。
  • 只要垃圾回收器没有回收它,该对象就可以被程序使用。
  • 软引用可以用来实现内存敏感的高速缓存
  • 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收, Java 虚拟机就会把这个软引用加入到与之关联的队列引用中。
    SoftReference<String[]> softBean = new SoftReference<String[]>(new String[]{"a", "b", "c"});
    

弱引用(WeakReference)

  • 只具有弱引用的对象拥有短暂的生命周期。只能生存到下一次垃圾发生收集之前。
  • 在垃圾回收器线程扫描它所管辖的内存区域中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存,
  • 不过由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象
  • 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收, java 虚拟机就会把这个弱引用加入到与之关联的引用队列中
    WeakReference<String[]> weakBean = new WeakReference<String[]>(new String[]{"a", "b", "c"});
    

注意: 并不是说只要GC就会把放在弱引用中的对象给回收的,一个对象被回收, 必须满足两个条件:

  1. 没有任何引用指向它(或者说gc root不可达)
  2. GC被运行. 也就是说尽管这个对象放在弱引用中,如果这个弱引用对象没有置为null,那么被弱引用的对象也不会被回收。

软引用和弱引用的选择

  • 如果只是为了避免 OOM 的发送,可以使用软引用,因为这个只是在内存不够的时候才会被回收,如果对应应用的性能更在意,想尽快回收一些占内存较大的对象,则使用弱引用,因为在下次 GC 的时候,就会被回收
  • 可以根据对数是否经常使用来判断使用软引用还是弱引用。如果该对象可能会经常被使用,则尽量使用软引用,如果该对象不被使用的可能性更大一些,就可以使用弱引用。

虚引用(PhantomReference)

顾名思义:形同虚设,虚引用并不会决定对象的什么周期,如果一个对象仅只有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。程序也并不能通过虚引用访问被引用的对象。 虚引用主要用来跟踪垃圾回收器回收的活动,虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用,当垃圾准备回收一个对象时,如果发现它还有虚引用,就会在回收对象内存之前,把这个虚引用加入到与之关联的队列中

ReferenceQueue<String[]> referenceQueue = new ReferenceQueue<String[]>();
PhantomReference<String[]> referent = new PhantomReference<String>(new String[]{"a", "b", "c"}, referenceQueue);

表格对比

类型 强引用 软引用 弱引用 虚引用
引用级别 最高 较高 较低
回收级别 不回收 较难回收 较易回收 容易回收
能否被 JVM 回收 不能 垃圾回收器工作并且内存不足条件下能回收 只要垃圾回收器工作就会回收 只要垃圾回收器工作就会回收
取得目标对象方式 直接调用 通过 get() 方法 通过 get() 方法 无法取得
用途 常住内存最高 内存敏感时代替强引用,常用于实现内存敏感的高速缓存 适用于存储元数据,如WeakHashMap(map 中的键值都被封装成了弱引用,一旦强引用被删除, WeakHashMap 就无法阻止该对象被垃圾回收器回收) 跟踪对象被垃圾回收的状态
是否可能内存泄露 可能 不可能 不可能 可能
比如 (面向对象的现实场景) 家里的必须生活用品,你不会扔掉 家里可有可无的生活用品,家里有空间的时候你会保留,家里没空间的时候你就会扔掉 家里没什么用的东西,比如生活垃圾,不管家里有没有空间,你都不想放到家里,随时都想把他扔掉 你想知道那些必要的东西是否还保留着,于是你借用了一个储物柜(按照顺序存放),可以看到那些东西你扔掉了,那些东西你没扔掉

搬运地址:

Java中的四种引用类型

Java内存回收机制–Java引用的种类(强引用、弱引用、软引用、虚引用)