强引用、软引用、弱引用、虚引用是什么,有什么区别?
在Java中提供了4个级别的引用:强引用、软引用、弱引用和虚引用。除强引用外,其他三种引用均可以在java.lang.ref包中找到它们的身影。
强引用,就是普通的对象引用关系,如 String s = new String(“ConstXiong”)
软引用,用于维护一些可有可无的对象。只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。SoftReference 实现
弱引用,相比软引用来说,要更加无用一些,它拥有更短的生命周期,当 JVM 进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。WeakReference 实现
虚引用是一种形同虚设的引用,在现实场景中用的不是很多,它主要用来跟踪对象被垃圾回收的活动。PhantomReference 实现
一.强引用:强引用就是就是程序中一般使用的引用类型,强引用的对象是可触及的,不会被回收。相对的,软引用、虚引用的对象是软可触及、弱可触及、虚可触及的,在一定条件下,都是可以被回收的。
下面是强引用的一个例子:
public class StrongReferenceTest01 {
public static void main(String[] args) {
StringBuffer stringbuffer = new StringBUffer(“我会发着呆,然后忘记你”);
StringBuffer stringbuffer1 = stringbuffer;
}
}
局部变量表stringbuffer被分配在栈上,而对象StringBuffer实例被分配在堆上。局部变量stringbuffer指向StringBuffer实例所在堆空间,通过stringbuffer可以操作该实例.那么stringbuffer就是StringBuffer实例的强引用。
那么,stringbuffer所指向的对象也将被stringbuffer1所指向,同时局部变量表上会分配空间存放stringbuffer变量,此时,该StringBuffer实例就有两个引用。该引用的“==”操作用于表示两操作数所指向的堆空间地址是否相同,不表示两操作数所指向的对象是否相等。
本例中的两个引用,都是强引用,强引用具备以下特点:
1.强引用可以直接访问目标对象。
2.强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用所指向对象。
3.强引用可能导致内存泄漏
public class StrongReferenceTest02 {
public static void main(String[] args) {
Student student = new Student(1,"geym");
// 建立软引用
SoftReference softReference = new SoftReference(student);
// 去除强引用
student = null;
System.out.println(softReference.get());
System.gc();
System.out.println("在进行垃圾回收之后:");
System.out.println(softReference.get());
// 分配一块较大的内存,让系统认为内存资源紧张
byte[] bytes = new byte[1024*925*7];
// 是多余的,因为在分配大数据时,系统会自动进行GC
System.gc();
System.out.println(softReference.get());
}
}
@Data
@AllArgsConstructor
@ToString
class Student {
private int id;
private String hobby;
}
GC未必会回收软引用的对象,但是当内存资源紧张时,软引用对象会回收,所以软引用对象不会引起内存溢出。
使用参数-Xmx10m运行以上代码。



