一、为啥有四种引用?
  在Java的世界中,如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。 这种定义很纯粹,但是太过狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些“食之无味,弃之可惜”的对象就显得无能为力。 我们希望能描述这样一类对象:当内存空间还足够时,则能保留在内存之中;如果内存空间在进行垃圾收集后还是非常紧张,则可以抛弃这些对象。 很多系统的缓存功能都符合这样的应用场景。

  所以,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

1、强引用(Strong Reference)

  强引用就是我们经常使用的引用,其写法如下:

 1 import java.io.IOException;
 2 
 3 public class T01_NormalReference {
 4     public static void main(String[] args) throws IOException {
 5         M m = new M();
 6         m = null;
 7         System.gc(); //DisableExplicitGC
 8 
 9         System.in.read();
10     }
11 }

 

 

2、软引用(Soft Reference)
  如果一个对象只具有软引用,在内存足够时,垃圾回收器不会回收它;如果内存不足,就会回收这个对象的内存。

  使用场景: 图片缓存。图片缓存框架中,“内存缓存”中的图片是以这种引用保存,使得 JVM 在发生 OOM 之前,可以回收这部分缓存。

 1 /**
 2  * 软引用
 3  * 软引用是用来描述一些还有用但并非必须的对象。
 4  * 对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。
 5  * 如果这次回收还没有足够的内存,才会抛出内存溢出异常。
 6  * -Xmx20M -Xms20M
 7  */
 8 
 9 import java.lang.ref.SoftReference;
10 
11 public class T02_SoftReference {
12     public static void main(String[] args) {
13         SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
14         //m = null;
15         System.out.println(m.get());
16         System.gc();
17         try {
18             Thread.sleep(500);
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22         System.out.println(m.get());
23 
24         //再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉
25         byte[] b = new byte[1024*1024*15];
26         System.out.println(m.get());
27     }
28 }

 

3、弱引用(Weak Reference)

  简单来说,就是将对象留在内存的能力不是那么强的引用。当垃圾回收器扫描到只具有弱引用的对象,不管当前内存空间是否足够,都会回收内存。

  使用场景:

  在下面的代码中,如果类 B 不是虚引用类 A 的话,执行 main 方法会出现内存泄漏的问题, 因为类 B 依然依赖于 A。

 1 public class Main {
 2     public static void main(String[] args) {
 3 
 4         A a = new A();
 5         B b = new B(a);
 6         a = null;
 7         System.gc();
 8         System.out.println(b.getA());  // null
 9 
10     }
11 
12 }
13 
14 class A {}
15 
16 class B {
17 
18     WeakReference<A> weakReference;
19 
20     public B(A a) {
21         weakReference = new WeakReference<>(a);
22     }
23 
24     public A getA() {
25         return weakReference.get();
26     }
27 }
View Code

相关文章:

  • 2021-05-21
  • 2021-08-16
  • 2021-10-23
  • 2021-09-11
  • 2021-05-23
猜你喜欢
  • 2022-02-20
  • 2021-08-09
  • 2022-01-09
  • 2021-09-03
  • 2022-12-23
  • 2022-12-23
  • 2021-06-27
相关资源
相似解决方案