概述
Java里存在四种类型的引用:强引用、软引用、弱引用和虚引用。
这四种引用类型,可以让我们决定对象的生命周期,利于JVM的GC回收,进而对内存溢出和内存泄漏可以有更好的解决途径。
Java的几种引用类型与可达性
引用类型 | 可达性 | 存在方式 | GC回收方式 |
---|---|---|---|
强可达 | 强引用 | 在一个线程内,无需引用直接可达 | 在引用存在的情况下不会回收 |
软可达 | 软引用 | 通过SoftReference 对象可达 | 内存不足时,根据使用频率进行清除 |
弱可达 | 弱引用 | 通过WeakReference 对象可达 | 当GC调用时,必定被回收 |
虚可达 | 虚引用 | 通过PhantomReference 对象可达 | 不影响生命周期 |
不可达 | 不存在 | 没有任何途径可达 | 调用即清除 |
强引用(Strong Reference)
- 强引用是最常用的引用,只要引用存在,就不会被回收。
- 只有在堆上的对象实例不存在任何引用指向它的时候,才会被回收。
- 若想让一个对象实例的空间释放,就应该关闭所有引用(赋予null)
String str = new String("This is a Strong Reference");//强引用
str = null;
System.gc(); //通知gc进行回收
通常我们不需要手动调用gc进行回收,系统会自动进行,这里仅仅只是作为演示。还需要注意的是:System.gc()
仅仅只是通知gc进行回收,并非会立即执行
软引用(Soft Reference)
- 软引用可以用来引用一些不那么重要的对象,可以是一些易失对象。
- 软引用的对象实例,只有在内存不足的时候JVM才会根据使用频率进行回收
- 在Java中用
java.lang.ref.SoftReference
类来表示 - 灵活使用软引用可以解决很多OOM(OutOfMemory)问题
- 应用场景:图片缓存,网页缓存 …
1)不使用引用队列
SoftReference<String> sr = new SoftReference<String> (new String("Soft Reference"));
System.gc();
System.out.println(sr.get());
2)使用引用队列
ReferenceQueue<String> Queue = new ReferenceQueue<String>();
SoftReference<String> sr = new SoftReference<String> (new String("Soft Reference"),Queue);
System.gc();
System.out.println(sr.get());
可以选择添加引用队列,这样一旦软引用的对象实例被 JVM回收,这个软引用就会被加入到与之关联的引用队列中
弱引用(WeakReference)
- 弱引用通常是用来作为临时引用
- 弱引用的对象实例,只要是系统调用gc回收的时候,必定会被清理
- 用
java.lang.ref.WeakReference
类来表示
WeakReference<String> wr = new WeakReference<String>(new String("Weak Reference"));
System.gc();
System.out.println(wr.get());
虚引用(PhantomReference)
唯一目的就是能在这个对象被回收时收到一个系统通知,虚引用主要用于检测对象是否已经从内存中删除
- 虚引用是用于检测对象是否已经从内存中删除,仅仅只有一个虚引用的对象是没有意义的,会被gc进行回收。
- 和软引用和弱引用不同的是,它不会对对象的生命周期造成影响
- 虚引用一定要与引用队列一同使用
String str = new String("This is a Phantom Reference")
ReferenceQueue<String> Queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(str,Queue);
str = null;
System.gc();
System.out.println(pr.isEnqueued());//判断是否已经被回收