java中的引用类型:
-
强引用 Strong Reference
在代码中普通使用的,类似Person person = new Person(); 如果一个对象具有强引用,则无论在什么情况下,GC都不会回收被引用的对象
。当内存空间不足时,Java虚拟机宁可抛出OutOfMemoryError终止应用程序也不会回收具有强引用的对象。 -
软引用 SoftReference
表示一个对象处在有用但非必须的状态。如果一个对象具有软引用,在内存空间充足时,GC就不会回收该对象;当内存空间不足时,GC会回收该对象的内存
(回收发生在OutOfMemoryError之前)。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被GC回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中,以便在恰当的时候将该软引用回收。但是由于GC线程的优先级较低通常手动调用System.gc()并不能立即执行GC,因此软引用所引用的对象并不一定会被马上回收。 -
弱引用 WeakReference
用来描述非必须的对象。它类似软引用,但是强度比软引用更弱一些:弱引用具有更短的生命,GC在扫描的过程中,一旦发现只具有被弱引用关联的对象,都会回收掉被弱引用关联的对象。换言之,无论当前内存是否紧缺,GC都将回收被弱引用关联的对象
。 -
虚引用 PhantomReferece
虚引用等同于没有引用,这意味着在任何时候都可能被GC回收,设置虚引用的目的是为了被虚引用关联的对象在被垃圾回收器回收时,能够收到一个系统通知。
(被用来跟踪对象被GC回收的活动)虚引用和弱引用的区别在于:虚引用在使用时必须和引用队列(ReferenceQueue)联合使用,其在GC回收期间的活动如下:
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = newe PhantomReference(object.queue);
也即是GC在回收一个对象时,如果发现该对象具有虚引用,那么在回收之前会首先该对象的虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入虚引用来了解被引用的对象是否被GC回收。
引用队列ReferenceQueue
-
ReferenceQueue含义及作用
通常我们将其ReferenceQueue翻译为引用队列,换言之就是存放引用的队列,保存的是Reference对象。其作用在于Reference对象所引用的对象被GC回收时,该Reference对象将会被加入引用队列中(ReferenceQueue)的队列末尾。 -
ReferenceQueue常用的方法:
public Reference poll():从队列中取出一个元素,队列为空则返回null;
public Reference remove():从队列中出队一个元素,若没有则阻塞至有可出队元素;
public Reference remove(long timeout):从队列中出队一个元素,若没有则阻塞至有可出队元素或阻塞至超过timeout毫秒;
对象的可及性由最强引用类型决定。
对象的可及性:
1)强可及对象:永远都不会被GC回收
2)软可及对象:当系统内存不足的时候,被GC回收
3)弱可及对象:当系统GC发现这个对象,就被回收
4)虚可及对象:当系统GC回收时可得到一个通知
虚引用功能:不会影响到对象的生命周期,但是能让程序员知道该对象什么时候被回收了。
package com.example.referencedemo;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class ReferenceTest {
public static void main(String[] args) {
String str = "abc"; //放到常量池中
// 创建一个软引用,引用到str
SoftReference<String> sfr = new SoftReference<>(str);
// 创建一个弱引用,引用到str
WeakReference<String> wrf = new WeakReference<>(str);
str = null; //相当于去掉了强引用链
String sfrString = sfr.get();
String wrfString = wrf.get();
System.out.println("软引用获取的对象:" + sfrString); //输出结果:软引用获取的对象:abc
System.out.println("弱引用获取的对象:" + wrfString); // 输出结果:弱引用获取的对象:abc
//清除软引用的引用链
sfr.clear();
sfrString = sfr.get();
System.out.println("软引用获取的对象:" + sfrString); //输出结果:软引用获取的对象:null
// 1.在堆内存中创建了String对象, 2.在常量池中创建了abc对象
String str2 = new String("abc");
WeakReference<String> wrf2 = new WeakReference<>(str2);
str2 = null; //相当于去掉了强引用链
System.gc(); //gc回收,回收堆内存的空间
String wrf2String = wrf2.get();
System.out.println("弱引用获取的对象:" + wrf2String); // 输出结果:弱引用获取的对象:null
}
}